一个简单的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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql datetime格式化日期(日期格式化)

    Mysql日期格式化查询问题写sql语句时发现怎么都查不出来数据,后来发现数据格式化后和前台传入的数据格式不一样。前台传入数据格式‘2018-11-5’原先sql查询语句(mybatis中)SELECTcount(*)count,a.store_idstoreid,DATE_FORMAT(a.timeone,’%Y-%m-%d’)mytime,s.abbrev…

    2022年4月13日
    117
  • Python:类的定义与使用

    Python:类的定义与使用类的定义与使用cball=Projectile(angle,vel,h0)中,cball传入给self一个炮弹从某个倾角射出计算水平位移和大致飞行时间的程序#projectile.p

    2022年7月5日
    21
  • list的五种去重方法

    list的五种去重方法面试中经常被问到的list如何去重,一般是口述,不需要代码体现,这个时候,思维一定要清晰,可以罗列出集中去重的方法,以展现你对list数据结构,以及相关方法的掌握,体现你的java基础学的是否牢固下面,我就将五种方法逐一展现新建一个list数组:Listlist=newArrayList();list.add(26);list.add(39);list.add(5)…

    2022年5月9日
    55
  • Java.Utils:AES-128-CBC 加密方式

    packagecom.boob.common.utils;importorg.apache.commons.codec.binary.Base64;importorg.bouncycastle.jce.provider.BouncyCastleProvider;importjavax.crypto.BadPaddingException;importjavax.crypto….

    2022年4月10日
    89
  • 数据库query用法_query方法

    数据库query用法_query方法1、以前写代码,总免不了要编写登录部分。在获取user的时候,只可能返回一个user实例,或者为null。以前使用以下方法实现:publicUserget(Stringname,Stringpassword){Sessionsession=HibernateUtil.getSessionFactory().openSession();String…

    2022年9月30日
    3
  • java流操作对文件的分割和合并

    学习文件的输入输出流,自己做一个小的示例,对文件进行分割和合并。

    2022年2月24日
    44

发表回复

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

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