1. 程式人生 > >Task CancellationTokenSource和Task.WhenAll的應用

Task CancellationTokenSource和Task.WhenAll的應用

quest 間接 結束 box str del 理解 delay 阻塞

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是異步的是不會阻塞線程的。

Task CancellationTokenSource和Task.WhenAll的應用