九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
C# 并行和多線程編程——認識和使用Task
對于多線程,我們經(jīng)常使用的是Thread。在我們了解Task之前,如果我們要使用多核的功能可能就會自己來開線程,然而這種線程模型在.net 4.0之后被一種稱為基于“任務的編程模型”所沖擊,因為task會比thread具有更小的性能開銷,不過大家肯定會有疑惑,任務和線程到底有什么區(qū)別呢?
任務和線程的區(qū)別:
1、任務是架構在線程之上的,也就是說任務最終還是要拋給線程去執(zhí)行。
2、任務跟線程不是一對一的關系,比如開10個任務并不是說會開10個線程,這一點任務有點類似線程池,但是任務相比線程池有很小的開銷和精確的控制。
一、認識Task和Task的基本使用
1、認識Task
首先來看一下Task的繼承結構。Task標識一個異步操作。
可以看到Task和Thread一樣,位于System.Threading命名空間下,這也就是說他們直接有密不可分的聯(lián)系。下面我們來仔細看一下吧!
2、創(chuàng)建Task
創(chuàng)建Task的方法有兩種,一種是直接創(chuàng)建——new一個出來,一種是通過工廠創(chuàng)建。下面來看一下這兩種創(chuàng)建方法:
1
2
3
4
5
//第一種創(chuàng)建方式,直接實例化
var task1 = new Task(() =>
{
//TODO you code
});
這是最簡單的創(chuàng)建方法,可以看到其構造函數(shù)是一個Action,其構造函數(shù)有如下幾種,比較常用的是前兩種。
1
2
3
4
5
//第二種創(chuàng)建方式,工廠創(chuàng)建
var task2 = Task.Factory.StartNew(() =>
{
//TODO you code
});
這種方式通過靜態(tài)工廠,創(chuàng)建以個Task并運行。下面我們來建一個控制臺項目,演示一下,代碼如下:
要添加System.Threading.Tasks命名控件引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskDemo
{
class Program
{
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Hello,task");
});
task1.Start();
var task2 = Task.Factory.StartNew(() =>
{
Console.WriteLine("Hello,task started by task factory");
});
Console.Read();
}
}
}
這里我分別用兩種方式創(chuàng)建兩個task,并讓他們運行??梢钥吹酵ㄟ^構造函數(shù)創(chuàng)建的task,必須手動Start,而通過工廠創(chuàng)建的Task直接就啟動了。
下面我們來看一下Task的聲明周期,編寫如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
var task1 = new Task(() =>
{
Console.WriteLine("Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Finish");
});
Console.WriteLine("Before start:" + task1.Status);
task1.Start();
Console.WriteLine("After start:" + task1.Status);
task1.Wait();
Console.WriteLine("After Finish:" + task1.Status);
Console.Read();
task1.Status就是輸出task的當前狀態(tài),其輸出結果如下:
可以看到調用Start前的狀態(tài)是Created,然后等待分配線程去執(zhí)行,到最后執(zhí)行完成。
從我們可以得出Task的簡略生命周期:
Created:表示默認初始化任務,但是“工廠創(chuàng)建的”實例直接跳過。
WaitingToRun: 這種狀態(tài)表示等待任務調度器分配線程給任務執(zhí)行。
RanToCompletion:任務執(zhí)行完畢。
二、Task的任務控制
Task最吸引人的地方就是他的任務控制了,你可以很好的控制task的執(zhí)行順序,讓多個task有序的工作。下面來詳細說一下:
1、Task.Wait
在上個例子中,我們已經(jīng)使用過了,task1.Wait();就是等待任務執(zhí)行完成,我們可以看到最后task1的狀態(tài)變?yōu)镃ompleted。
2、Task.WaitAll
看字面意思就知道,就是等待所有的任務都執(zhí)行完成,下面我們來寫一段代碼演示一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
Task.WaitAll(task1, task2);
Console.WriteLine("All task finished!");
Console.Read();
}
其輸出結果如下:
可以看到,任務一和任務二都完成以后,才輸出All task finished!
3、Task.WaitAny
這個用發(fā)同Task.WaitAll,就是等待任何一個任務完成就繼續(xù)向下執(zhí)行,將上面的代碼WaitAll替換為WaitAny,輸出結果如下:
4、Task.ContinueWith
就是在第一個Task完成后自動啟動下一個Task,實現(xiàn)Task的延續(xù),下面我們來看下他的用法,編寫如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static void Main(string[] args)
{
var task1 = new Task(() =>
{
Console.WriteLine("Task 1 Begin");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Task 1 Finish");
});
var task2 = new Task(() =>
{
Console.WriteLine("Task 2 Begin");
System.Threading.Thread.Sleep(3000);
Console.WriteLine("Task 2 Finish");
});
task1.Start();
task2.Start();
var result = task1.ContinueWith<string>(task =>
{
Console.WriteLine("task1 finished!");
return "This is task result!";
});
Console.WriteLine(result.Result.ToString());
Console.Read();
}
執(zhí)行結果如下:
可以看到,task1完成之后,開始執(zhí)行后面的內容,并且這里我們取得task的返回值。
在每次調用ContinueWith方法時,每次會把上次Task的引用傳入進來,以便檢測上次Task的狀態(tài),比如我們可以使用上次Task的Result屬性來獲取返回值。我們還可以這么寫:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var SendFeedBackTask = Task.Factory.StartNew(() => { Console.WriteLine("Get some Data!"); })
.ContinueWith<bool>(s => { return true; })
.ContinueWith<string>(r =>
{
if (r.Result)
{
return "Finished";
}
else
{
return "Error";
}
});
Console.WriteLine(SendFeedBackTask.Result);
首先輸出Get some data,然后執(zhí)行第二個獲得返回值true,最后根據(jù)判斷返回Finished或error。輸出結果:
Get some Data!
Finished
其實上面的寫法簡化一下,可以這樣寫:
1
Task.Factory.StartNew<string>(() => {return "One";}).ContinueWith(ss => { Console.WriteLine(ss.Result);});
輸出One,這個可以看明白了吧~
更多ContinueWith用法參見:http://technet.microsoft.com/zh-CN/library/dd321405
5、Task的取消
前面說了那么多Task的用法,下面來說下Task的取消,比如我們啟動了一個task,出現(xiàn)異?;蛘哂脩酎c擊取消等等,我們可以取消這個任務。
如何取消一個Task呢,我們通過cancellation的tokens來取消一個Task。在很多Task的Body里面包含循環(huán),我們可以在輪詢的時候判斷IsCancellationRequested屬性是否為True,如果是True的話就return或者拋出異常,拋出異常后面再說,因為還沒有說異常處理的東西。
下面在代碼中看下如何實現(xiàn)任務的取消,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
for (var i = 0; i < 1000; i++)
{
System.Threading.Thread.Sleep(1000);
if (token.IsCancellationRequested)
{
Console.WriteLine("Abort mission success!");
return;
}
}
}, token);
token.Register(() =>
{
Console.WriteLine("Canceled");
});
Console.WriteLine("Press enter to cancel task...");
Console.ReadKey();
tokenSource.Cancel();
Console.ReadKey();//這句忘了加,程序退出了,看不到“Abort mission success!“這個提示
這里開啟了一個Task,并給token注冊了一個方法,輸出一條信息,然后執(zhí)行ReadKey開始等待用戶輸入,用戶點擊回車后,執(zhí)行tokenSource.Cancel方法,取消任務。其輸出結果如下:
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C# 線程知識
8天玩轉并行開發(fā)
4.0中的并行計算和多線程詳解(二)
C# 異步編程
Task 類 (System.Threading.Tasks) | Microsoft Docs
(轉)改善C#程序的建議9:使用Task代替ThreadPool和Thread
更多類似文章 >>
生活服務
熱點新聞
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服