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

时间:2018-03-06 16:35:28 浏览量:419 阅读时间:19.45 分钟

八、   并行运行任务

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

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。程序运行结果。如下图。

     a

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

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

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

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

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

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

 2.程序界面如下图。

    b

 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处可以看出“异步交互”按钮无法显示。

 c

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

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

       d

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

 e

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

打赏

感谢您的支持,我会继续努力的!


支付宝
注册用户登录后才能发表评论,请 登录 注册,请访问 网站首页。
总计(0)条评论

admin

软件工程师

    文章目录

    返回顶部小火箭