zoukankan      html  css  js  c++  java
  • Task CancellationTokenSource和Task.WhenAll的应用

    Task是.net4.0推出的异步编程类,与ThreadPool.QueneUserWorkItem方法类似的是,Task也是使用线程池来工作的.但Task比起这个QueneUserWorkItem的优势是它的可控制性,能够通过CancellationTokenSource控制Task运行任务的取消,还能够知道Task运行任务是何时完成的.Task对线程的阻塞控制有静态方法WaitAll(params Task[] tasks)我的理解是,当所有的tasks都完成得时候线程就不会阻塞,WaitAny(params Task[] tasks))表示只要tasks中其中任意一个任务完成,线程就不会再是阻塞状态.,成员方法Wait方法有四个重载,它们分别是:

    • public void Wait()
    • public bool Wait(TimeSpan timeout)
    • public void Wait(CancellationToken cancellationToken)
    • public bool Wait(int millisecondsTimeout)
    • public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)

    对于Task的介绍就到这里,下面来看看它的一个例子,这个例子,我要做的就是:当点击按钮时,用两个任务t2,t3来sleep5秒钟,同时用任务t1在uI界面死循环的更新listbox读秒时间,当t2,t3任务结束了,在利用Task.WenAll和CancellationTokenSource break掉t1的死循环。效果如图所示:

    代码如下:

    CancellationTokenSource cts = new CancellationTokenSource();
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                Task t2 = new Task(() =>
                {
                    Thread.Sleep(5000);
                });
                //為了说明Task的异步,t2 和 t3都sleep5秒,但程序只数了5秒就结束了,这间接说明t2和t3是异步的
                Task t3 = new Task(() =>
                {
                    Thread.Sleep(5000);
                });
                //死循环读秒
                Task t1 = new Task((obj) =>
                {
    
                    object[] objs = obj as object[];
    
                    CancellationTokenSource cancellationToken = objs[0] as CancellationTokenSource;//这个控制任务取消的
    
                    string strParam = objs[1].ToString();
    
                    int i = 1;
                    while (true)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }
    
                        if (listBox1.InvokeRequired)
                        {
    
                            listBox1.Invoke(new Action(() =>
                            {
                                listBox1.Items.Add(strParam + ":" + i++);
    
                            }));
                        }
                        else
                        {
                            listBox1.Items.Add(strParam + ":" + i++);
                        }
    
                        Delay(1000);
    
                    }
                }, new object[2] { cts, "params" }, cts.Token);//这里随便写了一个参数,当任务需要参数的时候就“{ cts, "params" }“这样传,并且把控制任务取消的令牌cts.Token传进去
    if (button1.Text == "start") 
    { button1.Text
    = "sleep...";
    t1.Start(); t2.Start();
    t3.Start();
    Task task
    = Task.WhenAll(t2, t3);//这个WhenAll不会像WaitAll那样阻塞线程,所以会在t2和t3都sleep的情况下执行t1那个死循环线程
              //这里在建一个死循环任务去判断task是否完成 Task.Run(()
    => { while (true) { if (task.IsCompleted)//当t2和t3都完成得时候,这里就为true { cts.Cancel();//这里是对Task的取消操作,当执行了这句话时,这里cancellationToken.IsCancellationRequested就变成true
    MessageBox.Show("結束!"); break; } } }); } }

    大概就是这样,Task.WenAll是异步的是不会阻塞线程的。

  • 相关阅读:
    Dependency property changed example
    业务数据分析
    WPF : 以鼠标指针为中心缩放
    WPF待学习问题列表(未完)
    GirdView前台数据类型转换
    牛人的博客
    使用Xpath对XML进行模糊查询
    XPath语法
    【HDU】3415 Max Sum of MaxKsubsequence
    【HDU】3474 Necklace
  • 原文地址:https://www.cnblogs.com/HelloQLQ/p/10287480.html
Copyright © 2011-2022 走看看