一个简单的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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • SpringBoot(二十二)整合Mybatis,使用SqlSessionTemplate实现增删改查[通俗易懂]

    SpringBoot(二十二)整合Mybatis,使用SqlSessionTemplate实现增删改查[通俗易懂]在之前这篇基础上进行改造使用JdbcTemplate实现增删改查。SpringBoot版本:2.1.1目录结构如下:pom文件添加依赖,如下:<!–添加依赖以后Mybatis就自动配置好了,可以直接使用,具体自动配置代码到mybatis-spring-boot-autoconfigure包下查看–><!–上一篇博客里添加的spring-boot…

  • 【第一篇】Vue的初次邂逅

    【第一篇】Vue的初次邂逅  因为最近需要使用到Vue,所以打算将Vue的学习资料详细整理一份,感兴趣的小伙伴可以一起来哦。一、Vue基础介绍1.什么是Vue.jsVue.js是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机App,Vue语法也是可以用于进行手机App开发的,需要借助于Weex)Vue.js是前端的主流框架之一,和Angular.js、Rea…

  • 三维空间坐标系变换-旋转矩阵「建议收藏」

    三维空间坐标系变换-旋转矩阵「建议收藏」    空间中三维坐标变换一般由三种方式实现,第一种是旋转矩阵和旋转向量;第二种是欧拉角;第三种是四元数。这里先介绍旋转矩阵(旋转向量)与欧拉角实现三维空间坐标变换的方法以及两者之间的关系。    这里以常见的世界坐标系与相机坐标系间的变换为例。一、首先介绍从相机坐标系转换到世界坐标系,也就是比较通用的body到世界坐标系间的转换。    那么旋转的欧拉角按从世界坐标…

    2022年10月25日
  • docker镜像源_云原生技术

    docker镜像源_云原生技术Docker镜像的详细讲解,如何安装Docker、配置Docker镜像加速以及操作Docker镜像。

  • 网页播放rtsp视频流

    网页播放rtsp视频流网页播放rtsp视频流原文:https://blog.csdn.net/u011562107/article/details/78548605?locationNum=10&amp;fps=1RTSP协议(1)是流媒体协议。(2)RTSP协议是共有协议,并有专门机构做维护。(3)RTSP协议一般传输的是ts、mp4格式的流。(4)RTSP传输一般需要2-3个通…

    2022年10月18日
  • oracle触发器示例,Oracle触发器简单示例

    oracle触发器示例,Oracle触发器简单示例首先创建两张测试表:CREATETABLEtest(t_idNUMBER(4),t_nameVARCHAR2(20),t_ageNUMBER(2),t_sexCHAR);CREATETABLEtest_log(caozuoVARCHAR2(20),tdatedate);然后创建触发器并且进行测试:CREATEORREPLACETRIGGERtest_t…

发表回复

您的电子邮箱地址不会被公开。

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