• 多线程编程学习笔记——任务并行库(四)


    接上文 多线程编程学习笔记——任务并行库(一)

    接上文 多线程编程学习笔记——任务并行库(二)

     接上文 多线程编程学习笔记——任务并行库(三)

    八、   并行运行任务

            本示例学习如何同时运行多个任务,并且当任务全部完成或其中一个完成时,如何高效的得到通知。

    1.示例代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ThreadPoolDemo
    {  
    
        class Program
        {
    
            static void Main(string[] args)
            {
                Console.WriteLine(" 处理并行Task。。。。。");       
    
                    var task1 = new Task<int>(() => RunTask("任务 1", 3));     
    
            
    
                    var task2 = new Task<int>(() => RunTask("任务 2", 2));
                var whenTaskAll = Task.WhenAll(task1, task2);
    
                 whenTaskAll.ContinueWith(t => Console.WriteLine(" ——task1 结果值={0}---task2 结果值={1}",t.Result[0],t.Result[1]),
    TaskContinuationOptions.OnlyOnRanToCompletion); task1.Start(); task2.Start(); Thread.Sleep(
    5000); Console.WriteLine(" ——————————————————————"); var tasks = new List<Task<int>>(); for (int i = 3; i < 10; i++) { int cnt = i; var task = new Task<int>(() => RunTask(string.Format("任务 {0}",cnt), cnt)); tasks.Add(task); task.Start(); } while(tasks.Count>0) { var completedTask = Task.WhenAny(tasks).Result; tasks.Remove(completedTask); Console.WriteLine(" ——一个task 完成任务—结果值={0}", completedTask.Result); } Thread.Sleep(7000); Console.Read(); } private static int RunTask(string name,int seconds) { Console.WriteLine("Task {0} 运行在线程={1}中,是否在线程池 :{2}",name,
    Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread); Thread.Sleep(TimeSpan.FromSeconds(seconds));
    return 20 * seconds; } } }

    2。程序运行结果。如下图。

     

           当程序启动时,创建了两个任务(task1,task2),然后用task.whenall方法创建了第三个任务,这个任务会在所有任务完成之后运行。这个任务的结果提供了一个数组,第一个元素是第一个任务的结果,第二个元素是第二个任务的结果,以此类推。

            然后我们创建了一个任务列表,列表中有七个任务,然后使用task.whenany方法,等这一系列任务中的任何一个任务完成 ,就从列表中移除,并继续等待其他任务完成,直到列表为空。

    九、   使用taskScheduler配置任务的执行

          我们学习任务调度程序,通过异步代码与UI进行交互。所以本示例是创建Windows应用程序。

          taskScheduler是负责如何执行任务,默认情况下是把task放入线程池中的工作线程中。

     1.在visual studio 中创建一个windowsForm个界面,名称为FormTPL 这个界面中有同步,异步两个按钮。

     2.程序界面如下图。

     3.代码如下。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms; 
    
    namespace ThreadTPLDemo
    {
        public partial class FormTPL : Form
        {
    
            public FormTPL()
            {
                InitializeComponent();
    
            } 
    
            private void buttonSync_Click(object sender, EventArgs e)
            {
    
                try
                {
                    string result = RunTask().Result;
                    textBoxMsg.Text = result;
    
                }
                catch (Exception ex)
    
                {      
              textBoxMsg.Text = ex.Message;
                }      
    
            } 
    
            private void buttonAsync_Click(object sender, EventArgs e)
            {
                this.Cursor = Cursors.WaitCursor;
    
                Task<string> task = RunTask();
                task.ContinueWith(t =>
                {
                    textBoxMsg.Text = t.Exception.InnerException.Message;
                    this.Cursor = Cursors.Arrow;
                }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,TaskScheduler.FromCurrentSynchronizationContext());
     
            }
    
            private void buttonAsyncOk_Click(object sender, EventArgs e)
            {
    
                this.Cursor = Cursors.WaitCursor;
                Task<string> task = RunTask(TaskScheduler.FromCurrentSynchronizationContext());
                task.ContinueWith(t =>this.Cursor=Cursors.Arrow,
                CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
    
            }
    
            private Task<string> RunTask()
            {
                return RunTask(TaskScheduler.Default);
    
            }
     
    
            private Task<string> RunTask(TaskScheduler tsched)
            {
                Task delay = Task.Delay(TimeSpan.FromSeconds(5));
                return delay.ContinueWith(t =>
                {
                    string str = string.Format("Task 运行在线程={0},是否是在线程池中运行:{1}",Thread.CurrentThread.ManagedThreadId, 
    Thread.CurrentThread.IsThreadPoolThread); textBoxMsg.Text
    = str; return str; },tsched); } } }

     4。程序运行结果中会出现第一个问题,当点击同步按钮,执行程序时,整个应用 程序的用户界面假死,无法进行其他的任务操作。如下图。从图中2处可以看出“异步交互”按钮无法显示。

     

      5.  解决同步执行界面会假死的问题,我们使用异步执行的方式解决。

      6. 第二个问题,而且当我们从线程中直接访问UI界面中的控件时,会抛出异常。

          

       7. 当我们按第三个按钮,然后执行代码,程序正常运行,并得到结果。如下图。

     

     

          最后,本人不建议使用taskScheduler来开发任务调度程序,建议使用Quartz.Net来开发任务调度程序。

  • 相关阅读:
    Android和PHP开发最佳实践
    python3+pyqt5 +eric5安装配置
    用Python为iOS和Android写跨平台的应用
    No compatible targets were found Do you wish to a add new Android Virtual Device ?
    doc命令大全(详细版)
    安装Qt5.9
    ADT Bundle下载和安装
    阶段性学习内容
    DDMS files not found
    五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程
  • 原文地址:https://www.cnblogs.com/chillsrc/p/8023571.html
Copyright © 2020-2023  润新知