18
2016
08

.Net最简单的创建多线程主线程等待所有线程执行完成的例子

多线程运行,主线程等待。

        private static void Test2()
        {
            var waits = new List<EventWaitHandle>();
            for (int i = 0; i < 10; i++)
            {
                var handler = new ManualResetEvent(false);
                waits.Add(handler);
                new Thread(new ParameterizedThreadStart(Print))
                {
                    Name = "thread" + i.ToString()
                }.Start(new Tuple<int, EventWaitHandle>(i, handler));
            }
            WaitHandle.WaitAll(waits.ToArray());
            Console.WriteLine("All Completed!");
            Console.Read();
        }
        private static void Print(object param)
        {
            var p = (Tuple<int, EventWaitHandle>)param;
            Console.WriteLine(Thread.CurrentThread.Name + ": Begin!");
            if (p.Item1 == 2) Thread.Sleep(1200);
            else if (p.Item1 ==1 ) Thread.Sleep(2000);
            else Thread.Sleep(1000);
            Console.WriteLine(Thread.CurrentThread.Name + ": Print" + p.Item1);
            Console.WriteLine(Thread.CurrentThread.Name + ": End!");
            p.Item2.Set();
        }



附,一种变相多线程方法,Parallel.ForEach()或AsParallel():

并行 LINQ (PLINQ) 是 LINQ 模式的并行实现。 PLINQ 查询在许多方面类似于非并行 LINQ to Objects 查询。 PLINQ 尝试充分利用系统中的所有处理器, 它利用所有处理器的方法是,将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。 在许多情况下,并行执行意味着查询运行速度显著提高。

        private static void Test3()
        {
            var list=new List<int>();
            for(int i=0;i<100;i++)
            {
                list.Add(i);
            }
            Console.WriteLine("test3 start\n" + DateTime.Now);
            //并行循环
            Parallel.ForEach(list, (i) =>
            {
                Thread.Sleep(100);//遍历每个数字,休眠0.1秒
                //Console.WriteLine(i);
            });
            Console.WriteLine("test3  end\n" + DateTime.Now);
            Console.ReadKey();
        }
        private static void Test4()
        {
            var list = new List<int>();
            for (int i = 0; i < 100; i++)
            {
                list.Add(i);
            }
            Console.WriteLine("test4 start\n" + DateTime.Now);
            //顺序循环
            list.ForEach((i) =>
            {
                Thread.Sleep(100);//遍历每个数字,休眠0.1秒
                //Console.WriteLine(i);
            });
            Console.WriteLine("test4  end\n" + DateTime.Now);
            Console.ReadKey();
        }


附Parallel和普通循环执行结果:


分析:100个数,顺序一个一个执行,每个休眠100毫秒,总共 10秒。

而用Parallel并行计算,我电脑是2核4线程,应该是用了4线程,每4个同时执行,那100个就变成了100/4=25 次,共2.5秒,程序打印出来的时间,大概在2秒到3秒之间,估计得没错了。

Parallel适用于数据量大的情况(>10),如果数据少的话,还是不要用,因为使用硬件线程时,内部也是要用资源的。

要保证线程安全,一般使用对象:ConcurrentBag<T>来定义List类型集合。


Parallel更多用法,可参考:http://blog.csdn.net/sqlchen/article/details/26701403



新语法多线程使用:

using SystemTask = System.Threading.Tasks.Task;
   
      public string Test()
        {
            var className = "Test";// this.GetType().Name;
            var ret = className + ": start " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "<br/>";
            var task_1 = SystemTask.Factory.StartNew(() =>
            {
                //var StandardHotelScenicService2 = MefInjectionProvider.GetExport<IStandardHotelScenicService>();
                LogUtility.WriteLog("task_1: start " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                Thread.Sleep(3000);
                LogUtility.WriteLog("task_1: end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                throw new BusinessException("test");//异常会被捕捉
            });
            var task_2 = SystemTask.Factory.StartNew(() =>
            {
                LogUtility.WriteLog("task_2: start " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                Thread.Sleep(3000);
                LogUtility.WriteLog("task_2: end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
            });
            var task_3 = SystemTask.Factory.StartNew(() =>
            {
                LogUtility.WriteLog("task_3: start " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                Thread.Sleep(3000);
                LogUtility.WriteLog("task_3: end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
            });
            //输入参数类型object,输出类型指定为int
            var task_4 = SystemTask.Factory.StartNew<int>((a) =>
            {
                LogUtility.WriteLog("task_4: start " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 传入参数a:" + a.ToString(), false);
                Thread.Sleep(3000);
                LogUtility.WriteLog("task_4: end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                return Convert.ToInt32(a) + 10;
            }, 4);
            try
            {
                SystemTask.WaitAll(task_1, task_2, task_3, task_4);//等执行完毕,各task内如果有异常会在这里抛出
                LogUtility.WriteLog("task_4: 输出int参数值:" + task_4.Result + " ," + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
                LogUtility.WriteLog("SystemTask.WaitAll: end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), false);
            }
            catch (Exception ex)
            {
                ret += className + " task出错:" + new ExceptionMessage(ex).ToString();
            }
            ret += className + ": end " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            return ret;
        }


执行后,log日志内容:

[2017-08-14 11:50:41,273] task_1: start 2017-08-14 11:50:41
[2017-08-14 11:50:41,273] task_2: start 2017-08-14 11:50:41
[2017-08-14 11:50:41,273] task_3: start 2017-08-14 11:50:41
[2017-08-14 11:50:41,273] task_4: start 2017-08-14 11:50:41 传入参数a:4
[2017-08-14 11:50:44,282] task_1: end 2017-08-14 11:50:44
[2017-08-14 11:50:44,283] task_2: end 2017-08-14 11:50:44
[2017-08-14 11:50:44,283] task_3: end 2017-08-14 11:50:44
[2017-08-14 11:50:44,284] task_4: end 2017-08-14 11:50:44
[2017-08-14 11:50:44,284] 请求标识【1db40b7e-7172-4207-a362-62752edd43a7】task_4: 输出int参数值:14 ,2017-08-14 11:50:44
[2017-08-14 11:50:44,284] 请求标识【1db40b7e-7172-4207-a362-62752edd43a7】SystemTask.WaitAll: end 2017-08-14 11:50:44





版权声明:
作者:真爱无限 出处:http://www.pukuimin.top 本文为博主原创文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.
« 上一篇下一篇 »

相关文章:

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。