国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

.Net4.0 任務(Task)

2019-11-17 02:30:05
字體:
來源:轉載
供稿:網友
.Net4.0 任務(Task)

任務(Task)是一個管理并行工作單元的輕量級對象。它通過使用CLR的線程池來避免啟動專用線程,可以更有效率的利用線程池。System.Threading.Tasks 命名空間下任務相關類一覽:

作用
Task管理工作單元
Task<TResult>管理帶返回值的工作單元
TaskFactory創建任務
TaskFactory<TResult>創建任務或者有相同返回值的延續任務
TaskScheduler管理任務調度
TaskCompletionSource手動控制任務工作流

任務用來并行地執行工作,充分地利用多核:事實上,Parallel和PLINQ內部就是建立在任務并行的結構上。

任務提供了一系列強大的特性來管理工作單元,包括:

  • 協調任務調度
  • 建立一個任務從另一個任務中啟動的父子關系
  • 實現合作取消(coOperative cancellation)模式
  • 無信號的任務等待
  • 附加延續任務(continuation)
  • 基于多個祖先任務調度一個延續任務
  • 傳遞異常到父任務、延續任務或任務消費者

同時任務實現了一個本地工作隊列,它允許你高效地創建快速執行的子任務而不用遭受在單個工作隊列時的競爭花費。任務并行庫讓你用最小的花費來創建成百上千的任務,但是如果你想創建上百萬個任務,就必須分割這些任務到更大的工作單元,以保持效率。

創建與啟動任務

有兩種方法可以創建任務,一種是通過TaskFactory的StartNew()方法創建并啟動任務;另一種是調用Task構造函數創建,然后手動啟動任務。需要注意的是,任務啟動后并不會立即執行,它是由任務調度器(TaskScheduler)來管理的。

  • TaskFactory的StartNew()方法創建任務的示例如下:
    //沒有返回值Task.Factory.StartNew(() => Console.WriteLine("Task Created!"));//有返回值var task = Task.Factory.StartNew<string>(() => "Task Created!");Console.WriteLine(task.Result);
  • 調用Start方法手動啟動的示例如下:
    var task = new Task<string>(() => "Task Created!");task.Start();//異步執行Console.WriteLine(task.Result);
  • 調用RunSynchronously方法手動啟動的示例如下:
    var task = new Task<string>(() => "Task Created!");task.RunSynchronously();//同步執行Console.WriteLine(task.Result);

也可以在創建任務時指定一個任務狀態參數,可以通過任務的AsyncState屬性來訪問該參數。示例:

var task = Task.Factory.StartNew(state => "hello " + state, "Mike");Console.WriteLine(task.AsyncState);Console.WriteLine(task.Result);

你還可以指定一個任務創建選項(TaskCreationOptions) ,這個枚舉類型有以下枚舉值:None,LongRunning,PReferFairness,AttachedToParent。下面解釋各個枚舉值的作用。

  • LongRunning:顧名思義就是長時間運行的任務,此選項建議任務調度器分配一個專用的線程給任務。這樣做的原因是:長時間運行的任務可能會阻塞任務隊列,導致那些短小的任務一直得不到執行。LongRunning也適合那些阻塞的任務。
  • PreferFairness:公平第一,此選項建議任務調度器盡量按照任務的啟動時間來調度任務。但是它通常可能不這樣做,因為它使用本地工作偷取隊列(local work-stealing queues)優化任務調度。這個優化對那些非常小的任務很有用。
  • AttachToParent:附加到父任務,此選項用來創建子任務。創建子任務示例:復制代碼
    第一種方式:var parent = Task.Factory.StartNew(() =>{    var nonChildTask = Task.Factory.StartNew(        () => Console.WriteLine("I'm not a child task.")    );    var childTask = Task.Factory.StartNew(        () => Console.WriteLine("I'm a child task."),     TaskCreationOptions.AttachedToParent);}); 第二種方式:Task parent=new Task(()=>{    DoStep1();});Task task2 = parent.ContinueWith ((PrevTask) =>{    DoStep2();});parent.Start();
    復制代碼

任務等待

任務可以通過Wait()成員方法或Result屬性來等待任務完成。

當調用Result屬性時,將會執行下列操作:

  1. 如果任務已結束,返回任務結果
  2. 如果任務已開始,等待任務結束
  3. 如果任務尚未開始執行,則在當前線程執行任務

Task.WaitAny()靜態方法等待任何一個任務完成。示例:

復制代碼
var tasks = new Task[3];for (int i = 0; i < tasks.Length; i++){    int taskIndex = i;    tasks[i] = Task.Factory.StartNew(() =>    {        int seed=Guid.NewGuid().GetHashCode();        int waitTime = new Random(seed).Next(10, 100);        Thread.Sleep(waitTime);        Console.WriteLine("Task{0} Finished", taskIndex);    });}Task.WaitAny(tasks);Console.WriteLine("已有任務完成");
復制代碼

Task.WaitAll()靜態方法等待所有任務完成。即使有任務拋出異常也不會終止等待,它會在所有任務完成之后拋出一個AggregateException異常,這個異常聚合了所有任務拋出的異常。示例:

復制代碼
var tasks = new Task[3];for (int i = 0; i < tasks.Length; i++){    int taskIndex = i;    tasks[i] = Task.Factory.StartNew(() =>    {         int waitTime = new Random(Guid.NewGuid().GetHashCode()).Next(10, 100);         Thread.Sleep(waitTime);         Console.WriteLine("Task{0} Finished", taskIndex);    });}Task.WaitAll(tasks);Console.WriteLine("所有任務完成");
復制代碼

異常處理

默認情況下任務未處理的異常會終止應用程序。需要指出的是任務中未處理的異常不會立即導致應用程序終止,異常要延遲到垃圾回收器回收任務并調用Finalize方法時才會終止程序。如果讀取了任務的Exception屬性,這個操作將阻止隨后的應用程序終止。 當等待任務完成時,所有未處理的異常會傳遞到調用方。 Wait()方法超時的異常也必須處理,否則導致應用程序終止。 子任務中未處理的異常會冒泡傳遞到父任務;嵌套任務中的非子任務的異常不會傳遞到這個任務的上一層任務,需要單獨處理,否則將導致應用程序終止。

復制代碼
var task = Task.Factory.StartNew(() =>{    Task.Factory.StartNew(() => { throw null; }, TaskCreationOptions.AttachedToParent);    Task.Factory.StartNew(() => { throw null; }, TaskCreationOptions.AttachedToParent);    Task.Factory.StartNew(() => { throw null; }, TaskCreationOptions.AttachedToParent);});task.Wait();
復制代碼

TaskScheduler.UnobservedTaskException靜態事件提供了最后一種手段處理所有未處理異常。通過處理這個事件,就不用終止應用程序,而用你自己的異常處理邏輯替代它。

取消任務

當創建任務時,可以傳入一個取消令牌(CancelationToken)參數,這樣就可以安全的取消任務。示例:

復制代碼
var source = new CancellationTokenSource();var token = source.Token;var task = Task.Factory.StartNew(() =>{    Console.WriteLine("Task starting...");    while (true)    {        token.ThrowIfCancellationRequested();        Console.WriteLine("I'm alive. {0}",DateTime.Now);        Thread.Sleep(1000);    }},token);Task.Factory.StartNew(() =>{    Thread.Sleep(4500);    source.Cancel();});try{    task.Wait();    Console.WriteLine("Task stopped.");}catch (AggregateException e){    if (e.InnerException is OperationCanceledException)    {        Console.WriteLine("Task canceled.");    }    else    {        Console.WriteLine("errors.");    }}
復制代碼

通過調用CancellationTokenSource的Cancel()方法取消任務,這個并不會立即終止任務,一直延遲到任務下次檢測是否取消時才通過拋出OperationCanceledException終止任務。

如果想通過直接拋出OperationCanceledException異常的方式取消任務,則需要在任務中傳入CancelationToken參數,否則就不能將任務的狀態為TaskStatus.Canceled并觸發OnlyOnCanceled延續任務。

此外,取消令牌也可以傳遞到Wait和CancelAndWait方法中來取消等待。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 合作市| 兰考县| 齐齐哈尔市| 杭锦后旗| 青川县| 寻乌县| 玉林市| 祁东县| 同江市| 旬邑县| 聊城市| 镇安县| 阳原县| 卢湾区| 宜章县| 山阳县| 壤塘县| 瓮安县| 平塘县| 新邵县| 黄浦区| 烟台市| 古蔺县| 汝南县| 七台河市| 盐源县| 忻州市| 揭阳市| 白山市| 宜宾市| 察雅县| 宽甸| 盱眙县| 茌平县| 育儿| 新邵县| 城固县| 突泉县| 安塞县| 葵青区| 张家界市|