一个简单的Parallel.ForEach实现

一个简单的Parallel.ForEach实现在.net的TaskParallelLibrary中有一个很方便的功能Parallel.ForEach,可以实现多任务的并发执行,另外还带着栅栏功能,非常好用。但是这一功能必须需要clr4.0支持(CTP版的不大好用),对于低版本的.net要实现类似功能只有自己写一个了。codeproject上面文章PoorMan’sParallel.ForEachIterator中就有一种简单而…

大家好,又见面了,我是你们的朋友全栈君。

在.net的Task Parallel Library中有一个很方便的功能Parallel.ForEach,可以实现多任务的并发执行,另外还带着栅栏功能,非常好用。但是这一功能必须需要clr4.0支持(CTP版的不大好用),对于低版本的.net要实现类似功能只有自己写一个了。

codeproject上面文章Poor Man’s Parallel.ForEach Iterator中就有一种简单而有效的实现。但作者附录的代码有如下几个问题:

  1. 无法对每个并发任务分别制定不同的线程数
  2. 算法本身有点问题,任务执行完会报错
  3. 不能快速响应异常

针对以上几点,我对那段代码做了一点小改进,代码如下:

static class Parallel
{

    public static void ParallelForEach<T>(this IEnumerable<T> enumerable, Action<T> action, int NumberOfParallelTasks)
    {

        var syncRoot = new object();

        if (enumerable == null) return;

        var enumerator = enumerable.GetEnumerator();

        InvokeAsync<T> del = InvokeAction;

        var seedItemArray = new T[NumberOfParallelTasks];
        var resultList = new List<IAsyncResult>(NumberOfParallelTasks);
        var waitHanles = new List<WaitHandle>(NumberOfParallelTasks);

        for (int i = 0; i < NumberOfParallelTasks; i++)
        {

            lock (syncRoot)
            {

                if (!enumerator.MoveNext())
                    break;
                seedItemArray[i] = enumerator.Current;
            }

            var iAsyncResult = del.BeginInvoke(enumerator, action, seedItemArray[i], syncRoot, i, null, null);
            resultList.Add(iAsyncResult);
            waitHanles.Add(iAsyncResult.AsyncWaitHandle);
        }

        var taskCount = waitHanles.Count;

        for (int i = 0; i < taskCount; i++)
        {

            var index = WaitHandle.WaitAny(waitHanles.ToArray());
            del.EndInvoke(resultList[index]);
            resultList[index].AsyncWaitHandle.Close();
            waitHanles.RemoveAt(index);
            resultList.RemoveAt(index);
        }
    }

    delegate void InvokeAsync<T>(IEnumerator<T> enumerator,
    Action<T> achtion, T item, object syncRoot, int i);

    static void InvokeAction<T>(IEnumerator<T> enumerator, Action<T> action,
            T item, object syncRoot, int i)
    {

        //if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
        // Thread.CurrentThread.Name =
        //String.Format(“Parallel.ForEach Worker Thread No:{0}”, i);

        bool moveNext = true;

        while (moveNext)
        {

            try
            {

                action.Invoke(item);
            }
            catch (Exception)
            {

                throw;
            }

            lock (syncRoot)
            {

                moveNext = enumerator.MoveNext();
                if (moveNext)
                    item = enumerator.Current;
            }
        }
    }
}

整个算法非常简洁,这里就不多介绍了。如果有错误欢迎指正。

转载于:https://www.cnblogs.com/TianFang/archive/2009/06/28/1512588.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161829.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SQL Server实现某书店图书进货、销售管理系统[通俗易懂]

    SQL Server实现某书店图书进货、销售管理系统[通俗易懂]  文末附带数据库文件及数据库日志文件地址。 一.需求分析1、背景(1)待开发的系统名称:图书进货、销售管理系统(2)开发者:FriggaAZ(3)用户:书店管理人员(4)开发环境:① 操作系统:Windows10专业版Build17682② 数据库:SQLServer2017Developer2、系统总体功能分析需求(1)…

    2022年5月6日
    139
  • 分子模拟软件amber_分子模拟周刊: 第 23 期

    分子模拟软件amber_分子模拟周刊: 第 23 期■2020-06-1221:34:10每周杂记:谢谢记得父亲突然联系我,说,我初中的班主任让我发一张照片,同时写一段自我介绍用来给他们现在的学生做榜样.这让我大感意外.这些老师都已经近30年未见过面了,竟还记得我?再说,以我现在这样的境况,用来给人做榜样是不是有点难堪?其实这个老师并不是我初中时候的班主任,是我的语文老师.他人长得很高大,声音洪亮,性格粗线条…

    2022年5月26日
    156
  • laravel 踩坑 env,config

    laravel 踩坑 env,config

    2021年10月26日
    43
  • 查看linux执行的命令记录_history命令用法

    查看linux执行的命令记录_history命令用法前言我们每次敲打linux命令的时候,有时候想用之前用过的命令,一般情况下,我们都会按↑↓箭头来寻找历史的命令记录,那如果我想用1天前执行的某条命令,难道还要按↑100次?显示这样是不现实的,我们可

    2022年7月29日
    5
  • 设置SVN忽略文件和文件夹(文件夹)

    设置SVN忽略文件和文件夹(文件夹)

    2021年12月14日
    55
  • 通配符掩码

    通配符掩码在访问控制列表中,通配符掩码来指定主机、特定网络或网络的一部分,首先要理解块大小,其用于指定地址范围块大小包括128、64、32、16、8、4等,在需要指定地址范围时,可使用能满足需求的最小块大小,

    2022年7月1日
    25

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号