zoukankan      html  css  js  c++  java
  • .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         }

       

  • 相关阅读:
    Java线程安全和非线程安全
    时间戳获取(周,年,月,日)
    spring+spring 日志输出
    Spring+springMvc+Mybatis
    关于mysql处理百万级以上的数据时如何提高其查询速度的方法
    Tomcat 详解
    理解 $_POST、$_GET 、php://input
    php编译参数注解--不明白许多参数的作用 慎用 –with-curlwrappers参数【转载】
    centos6.5编译安装php[整理一]
    ubuntu16.04 安装chrome 和 phpstorm
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/7071511.html
Copyright © 2011-2022 走看看