.Net进阶系列(13)-异步多线程(Task和Parallel)(被替换)

一. Task开启多线程的三种形式

 1. 利用TaskFactory下的StartNew方法,向StartNew传递无参数的委托,或者是Action<object>委托。

    2. 利用Task.Run()开启多线程,能向其中传递无参数的委托,有参数的可以使用  Task.Run(()=>{   TestThread("ypf")  })这种形式。(推荐这种方式,最简洁。)

    3. 先实例化Task,然后调用Start方法进行线程的开启。 Task构造函数可以无参委托或无参委托+object类型参数。   (同样道理,无参委托赋值有参函数,可以用之前的方案解决)

 1      public static void Test4()
 2         {
 3             //一. 各种委托的赋值
 4             //1. 无参数委托(包括方法有参数,如何赋值给无参委托)
 5             Action act1 = TestThread3;
 6             Action act2 = () => TestThread2("测试参数1");
 7             Action act3 = () => TestThread("测试参数1", "测试参数2");
 8 
 9             //2. 和方法参数对应的委托
10             Action act4 = () => TestThread3();
11             Action<string> act5 = t => TestThread2(t);
12             Action<string, string> act6 = (m, n) => TestThread(m, n);
13 
14             //3. Action<object>委托
15             Action<object> act7 = t => TestThread3();
16             Action<object> act8 = t => TestThread2(t.ToString());
17             //多个参数的函数要用实例类的方法解决
18 
19             //4. 委托赋值时不传参数,调用的时候传递
20             Action act9 = TestThread3;
21             Action<string> act10 = TestThread2;
22             Action<string, string> act11 = TestThread;
23 
24             //二. TaskFactory多线程的几种情况
25             TaskFactory taskFactory = new TaskFactory();
26             //1. 调用无参委托不需要传递参数
27             //{
28             //    taskFactory.StartNew(act1);
29             //    taskFactory.StartNew(act2);
30             //    taskFactory.StartNew(act3);
31             //}
32 
33             //2. 调用和方法参数对应的委托,需要在调用的时候传递参数
34             //{
35             //    taskFactory.StartNew(act4);
36             //    taskFactory.StartNew(act5, "测试参数1");  //不支持(StartNew没有这种重载)
37             //    taskFactory.StartNew(act6, "测试参数1", "测试参数2");  //不支持(StartNew没有这种重载)
38             //}
39 
40             //3. 调用Action<object>委托
41             //{
42             //    taskFactory.StartNew(act7,"");
43             //    taskFactory.StartNew(act8, "测试参数1");
44             //}
45 
46             //4. 调用 委托赋值时不传参数,调用的时候传递
47             //{
48             //    taskFactory.StartNew(act9);
49             //    taskFactory.StartNew(act10, "测试参数1");  //不支持(StartNew没有这种重载)
50             //    taskFactory.StartNew(act11, "测试参数1", "测试参数2");  //不支持(StartNew没有这种重载)
51             //}
52 
53             //三. 使用Task.Run() 多线程的几种情况
54             //1. 调用无参委托不需要传递参数
55             //{
56             //    Task.Run(act1);
57             //    Task.Run(act2);
58             //    Task.Run(act3);
59             //    Task.Run(act4);
60             //    Task.Run(act9);
61             //}
62             //除了上述五种方式,其他均不支持
63 
64             //四. 利用Task实例下的Start方法开启多线程
65             //1.act1 act2 act3 act4 act9  调用无参委托不需要传递参数,均可以调用
66             //{
67             //    Task task = new Task(act9);
68             //    task.Start();
69             //}
70             //2. Action<object>委托可以使用
71             //act7和act8可以调用
72             {
73                 Task task = new Task(act7, "");
74                 task.Start();
75             }
76             {
77                 Task task = new Task(act8, "测试参数1");
78                 task.Start();
79             }
80 
81         }

二. 线程等待的两种形式

    1. 利用Task下的静态方法WaitAll和WaitAny,来进行线程等待。(如果是主线程执行,则卡主主线程,如果新建一个子线程执行,则卡主了子线程)

     2. 利用TaskFactory下的ContinueWhenAny和ContinueWhenAll,来进行线程等待。

三. Parallel并行计算

 1. 并行计算和多线程的区别:

     多线程:如果要线程等待,需要单独开辟一个线程来进行线程等待,主线程在那等着。

     并行计算:开启多个线程,默认就是线程等待,主线程在那等着,所以会卡主线程。

 2. 并行计算的三种形式

    Parallel.Invoke();

    Parallel.For();

    Parallel.ForEach()

 1      private void button6_Click(object sender, EventArgs e)
 2         {
 3             Stopwatch watch = new Stopwatch();
 4             watch.Start();
 5             Console.WriteLine("----------------- 七.并行运算Parallel  --------------------------");
 6             Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
 7 
 8             //下面的测试结果发现,主线程均被卡住
 9             //并行计算和多线程相比的区别: 多线程执行后,需要单独再开辟一个线程等待,然后主线程在执行。 而并行计算,开启多个线程后,不需要再开辟线程等待,直接是主线程完成后续操作
10 
11             #region 写法一
12             //{
13             //    Parallel.Invoke(() => this.TestThread("bct1")
14             //                   , () => this.TestThread("bct2")
15             //                   , () => this.TestThread("bct3")
16             //                   , () => this.TestThread("bct4")
17             //                   , () => this.TestThread("bct5")
18             //    );
19             //}
20             #endregion
21 
22             #region 写法二
23             //{
24             //    //前两个参数之间的差,就为并行计算线程的个数
25             //    Parallel.For(5, 10, t =>
26             //    {
27             //        //这里的t分别为:5,6,7,8,9 五个数
28             //        string name = string.Format("bct{0}", t);
29             //        this.TestThread(name);
30             //    });
31             //}
32             #endregion
33 
34             #region 写法三
35             //{
36             //    //数组里的个数,就为并行计算线程的个数
37             //    Parallel.ForEach(new int[] { 3, 5, 44, 55, 100 }, t =>
38             //          {
39             //              //这里的t分别为:3, 5, 44, 55, 100五个数
40             //              string name = string.Format("bct{0}", t);
41             //              this.TestThread(name);
42             //          });
43             //}
44             #endregion
45 
46             #region 写法四
47             {
48                 ParallelOptions po = new ParallelOptions()
49                 {
50                     MaxDegreeOfParallelism = 5    //表示最大线程数为5,后面即使配置超过5,也无效
51                 };
52                 Parallel.For(6, 15, po, (t, state) =>
53                 {
54                     string name = string.Format("bct{0}", t);
55                     this.TestThread(name);
56                     //state.Break();   //退出单次循环(没看到实际作用)
57                     // state.Stop();     //退出全部循环(没看到实际作用)
58                     //return;
59                 });
60             }
61             #endregion
62 
63             watch.Stop();
64             Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
65 
66         }

 

   

 

posted @ 2017-06-23 20:00  Yaopengfei  阅读(617)  评论(0编辑  收藏  举报