亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何用Task替換Thread和ThreadPool?

發布時間:2020-05-27 15:00:20 來源:億速云 閱讀:269 作者:鴿子 欄目:編程語言

一:Task的優勢

ThreadPool相比Thread來說具備了很多優勢,但是ThreadPool卻又存在一些使用上的不方便。比如:

1: ThreadPool不支持線程的取消、完成、失敗通知等交互性操作;

2: ThreadPool不支持線程執行的先后次序;

以往,如果開發者要實現上述功能,需要完成很多額外的工作,現在,FCL中提供了一個功能更強大的概念:Task。Task在線程池的基礎上進行了優化,并提供了更多的API。在FCL4.0中,如果我們要編寫多線程程序,Task顯然已經優于傳統的方式。

以下是一個簡單的任務示例:

staticvoid Main(string[] args)
{
Task t =new Task(() =>
{
Console.WriteLine("任務開始工作……");
//模擬工作過程
Thread.Sleep(5000);
});
t.Start();
t.ContinueWith((task) =>
{
Console.WriteLine("任務完成,完成時候的狀態為:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
});
Console.ReadKey();
}

二:Task的完成狀態

任務Task有這樣一些屬性,讓我們查詢任務完成時的狀態:

1: IsCanceled,因為被取消而完成;

2: IsCompleted,成功完成;

3: IsFaulted,因為發生異常而完成

需要注意的是,任務并沒有提供回調事件來通知完成(像BackgroundWorker一樣),它通過啟用一個新任務的方式來完成類似的功能。ContinueWith方法可以在一個任務完成的時候發起一個新任務,這種方式天然就支持了任務的完成通知:我們可以在新任務中獲取原任務的結果值。

   下面是一個稍微復雜一點的例子,同時支持完成通知、取消、獲取任務返回值等功能:
staticvoid Main(string[] args)
{
CancellationTokenSource cts =new CancellationTokenSource();
Task<int> t =new Task<int>(() => Add(cts.Token), cts.Token);
t.Start();
t.ContinueWith(TaskEnded);
//等待按下任意一個鍵取消任務
Console.ReadKey();
cts.Cancel();
Console.ReadKey();
}

staticvoid TaskEnded(Task<int> task)
{
Console.WriteLine("任務完成,完成時候的狀態為:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
Console.WriteLine("任務的返回值為:{0}", task.Result);
}

staticint Add(CancellationToken ct)
{
Console.WriteLine("任務開始……");
int result =0;
while (!ct.IsCancellationRequested)
{
result++;
Thread.Sleep(1000);
}
return result;
}

在任務開始后大概3秒鐘的時候按下鍵盤,會得到如下的輸出:

任務開始……
任務完成,完成時候的狀態為:
IsCanceled=False IsCompleted=True IsFaulted=False
任務的返回值為:3
你也許會奇怪,我們的任務是通過Cancel的方式處理,為什么完成的狀態IsCanceled那一欄還是False。這是因為在工作任務中,我們對于IsCancellationRequested進行了業務邏輯上的處理,并沒有通過ThrowIfCancellationRequested方法進行處理。如果采用后者的方式,如下:

staticvoid Main(string[] args)
{
CancellationTokenSource cts =new CancellationTokenSource();
Task<int> t =new Task<int>(() => AddCancleByThrow(cts.Token), cts.Token);
t.Start();
t.ContinueWith(TaskEndedByCatch);
//等待按下任意一個鍵取消任務
Console.ReadKey();
cts.Cancel();
Console.ReadKey();
}

staticvoid TaskEndedByCatch(Task<int> task)
{
Console.WriteLine("任務完成,完成時候的狀態為:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
try
{
Console.WriteLine("任務的返回值為:{0}", task.Result);
}
catch (AggregateException e)
{
e.Handle((err) => err is OperationCanceledException);
}
}

staticint AddCancleByThrow(CancellationToken ct)
{
Console.WriteLine("任務開始……");
int result =0;
while (true)
{
ct.ThrowIfCancellationRequested();
result++;
Thread.Sleep(1000);
}
return result;
}

那么輸出為:

任務開始……
任務完成,完成時候的狀態為:
IsCanceled=True IsCompleted=True IsFaulted=False
在任務結束求值的方法TaskEndedByCatch中,如果任務是通過ThrowIfCancellationRequested方法結束的,對任務求結果值將會拋出異常OperationCanceledException,而不是得到拋出異常前的結果值。這意味著任務是通過異常的方式被取消掉的,所以可以注意到上面代碼的輸出中,狀態IsCancled為True。

再一次,我們注意到取消是通過異常的方式實現的,而表示任務中發生了異常的IsFaulted狀態卻還是等于False。這是因為ThrowIfCancellationRequested是協作式取消方式類型CancellationTokenSource的一個方法,CLR進行了特殊的處理。CLR知道這一行程序開發者有意為之的代碼,所以不把它看作是一個異常(它被理解為取消)。要得到IsFaulted等于True的狀態,我們可以修改While循環,模擬一個異常出來:

while (true)
{
//ct.ThrowIfCancellationRequested();
if (result ==5)
{
thrownew Exception("error");
}
result++;
Thread.Sleep(1000);
}

模擬異常后的輸出為:

任務開始……
任務完成,完成時候的狀態為:
IsCanceled=False IsCompleted=True IsFaulted=True

三:任務工廠

Task還支持任務工廠的概念。任務工廠支持多個任務之間共享相同的狀態,如取消類型CancellationTokenSource就是可以被共享的。通過使用任務工廠,可以同時取消一組任務:

staticvoid Main(string[] args)
{
CancellationTokenSource cts =new CancellationTokenSource();
//等待按下任意一個鍵取消任務
TaskFactory taskFactory =new TaskFactory();
Task[] tasks =new Task[]
{
taskFactory.StartNew(() => Add(cts.Token)),
taskFactory.StartNew(() => Add(cts.Token)),
taskFactory.StartNew(() => Add(cts.Token))
};
//CancellationToken.None指示TasksEnded不能被取消
taskFactory.ContinueWhenAll(tasks, TasksEnded, CancellationToken.None);
Console.ReadKey();
cts.Cancel();
Console.ReadKey();
}

staticvoid TasksEnded(Task[] tasks)
{
Console.WriteLine("所有任務已完成!");
}

以上代碼輸出為:

任務開始……
任務開始……
任務開始……
所有任務已完成(取消)!
本建議演示了Task(任務)和TaskFactory(任務工廠)的使用方法。Task甚至進一步優化了后臺線程池的調度,加快了線程的處理速度。在FCL4.0時代,使用多線程,我們理應更多地使用Task。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

紫金县| 天镇县| 兴山县| 大悟县| 丽江市| 谢通门县| 凤翔县| 原阳县| 洪泽县| 瑞丽市| 浮梁县| 怀柔区| 万载县| 富顺县| 凉城县| 万安县| 云南省| 炉霍县| 耿马| 拜泉县| 木兰县| 嘉定区| 黄石市| 邛崃市| 安陆市| 额尔古纳市| 延津县| 仙居县| 锡林浩特市| 清丰县| 繁峙县| 古浪县| 揭东县| 论坛| 邻水| 南开区| 蕉岭县| 克拉玛依市| 武冈市| 肇源县| 江西省|