日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程编程学习笔记——任务并行库(二)

發(fā)布時間:2025/3/19 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程编程学习笔记——任务并行库(二) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

接上文 多線程編程學習筆記——任務并行庫(一)

?

?

三、?? 組合任務

?

??????? 本示例是學習如何設置相互依賴的任務。我們學習如何創(chuàng)建一個任務的子任務,這個子任務必須在父任務執(zhí)行結束之后,再執(zhí)行。

?

1,示例代碼如下:

?

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ThreadTPLDemo {class Program{static void Main(string[] args){Console.WriteLine("Task 組合操作 ————"); Task<string> task1 =CreateTask("Task1",3);Task<string> task2 = CreateTask("Task2", 2);//給task1創(chuàng)建一個延續(xù)操作(子操作)task1.ContinueWith(t => Console.WriteLine("task1子操作:{0},線程ID:{1},是不是線程池中的線程:{2}",
t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),TaskContinuationOptions.OnlyOnRanToCompletion); task1.Start();task2.Start();
Thread.Sleep(TimeSpan.FromSeconds(4)); Task task3=task2.ContinueWith(t => Console.WriteLine("task2子操作:{0},線程ID:{1},是不是線程池中的線程:{2}",
t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread),
TaskContinuationOptions.OnlyOnRanToCompletion|TaskContinuationOptions.ExecuteSynchronously); task3.GetAwaiter().OnCompleted(() => Console.WriteLine("task3異步操作完成,線程ID:{0},是不是線程池中的線程:{1}",
Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread));Thread.Sleep(TimeSpan.FromSeconds(
2));Console.WriteLine("--------------父子任務--------------"); var task5= new Task<string>(() => {var task6 = Task.Factory.StartNew(() => TaskOper("子任務Task6", 5), TaskCreationOptions.AttachedToParent);task6.ContinueWith(t=>TaskOper("延時操作 task7",2),TaskContinuationOptions.AttachedToParent);return TaskOper("task5", 2);});task5.Start();while (!task5.IsCompleted){Console.WriteLine(" task5狀態(tài)——{0}", task5.Status);Thread.Sleep(500);}Console.WriteLine(" ——task5狀態(tài)—{0}", task5.Status);string result = task5.Result;Console.WriteLine(" task5運行結果——{0}", result);Console.ReadKey();}private static string TaskOper(string name,int seconds){ Console.WriteLine("Task 線程 ID:{0} 上,是不是線程池中的線程:{1},名稱: {2}",Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread, name);Thread.Sleep(TimeSpan.FromSeconds(seconds));return string.Format("線程ID:{0},名稱:{1}:秒:{2}", Thread.CurrentThread.ManagedThreadId,name,seconds);}static Task<string> CreateTask(string name,int seconds){return new Task<string>(() => TaskOper(name,seconds));}} }

2.程序運行結果如下圖。

?

?

?????? 如結果所示,程序在啟動時創(chuàng)建了兩個任務task1與task2,并為第一個任務創(chuàng)建了一個子操作。啟動這兩個任務,然后等待4秒,然后給第task2運行子操作,并通過TaskContinuationOptions. OnlyOnRanToCompletion的選項嘗試同步執(zhí)行這個子操作。如果子操作的運行時間非常短,則以上方式非常有用,因為放在主線程中運行比放在線程池運行要快。

?

????? 如果我們注釋掉那等待4秒的代碼(藍色字體),task2這個操作就會被放到線程池中,如下圖。

?

?

?

????? 接著,我們對task2任務的子操作定義了一個子操作task3,對task3使用新的GetAwaiter和Oncompleted方法,來執(zhí)行一個后續(xù)操作。

?

?????? 最后我們創(chuàng)建了一個新的任務task5,通過TaskContinuationOptions. AttachedToParent選項來運行一個子任務task6與后續(xù)操作task7。

?

?

?

四、?? 將APM模式轉為任務

?

????????? 本示例,將上一篇(多線程編程學習筆記——線程池(一))中的(示例一線程池中調用委托)轉為任務。將APM轉換為TPL的關鍵是Task<T>.Factory.FromAsync()方法

?

?1.代碼如下:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ThreadTPLDemo { public delegate string AsyncTaskRun(string name);public delegate string IncompAsyncTaskRun(out int threadId);class Program{static void Main(string[] args){Console.WriteLine(" 將APM模式轉為Task。。。");int threadId = 0;AsyncTaskRun tkDele = RunTask;IncompAsyncTaskRun taskDele = RunTask; Console.WriteLine(" --------1------------");Task<string> task1=Task<string>.Factory.FromAsync(tkDele.BeginInvoke("task1", Callback, "Task異步調用回調函數(shù)"),tkDele.EndInvoke);task1.ContinueWith(t => Console.WriteLine("task1回調函數(shù)執(zhí)行結束,執(zhí)行后續(xù)子操作:{0}", t.Result)); while (!task1.IsCompleted){Console.WriteLine(" task1狀態(tài)——{0}", task1.Status);Thread.Sleep(500);}Console.WriteLine(" ——task1狀態(tài)—{0}", task1.Status);Thread.Sleep(2000); Console.WriteLine();Console.WriteLine(" ---------------2-----------——");Task<string> task2 = Task<string>.Factory.FromAsync(tkDele.BeginInvoke,tkDele.EndInvoke,"task2", "Task異步調用回調函數(shù)");task2.ContinueWith(t => Console.WriteLine("task2 回調函數(shù)執(zhí)行結束,執(zhí)行后續(xù)子操作:{0}", t.Result)); while (!task2.IsCompleted){Console.WriteLine(" task2狀態(tài)——{0}", task2.Status);Thread.Sleep(500);}Console.WriteLine(" ——task2狀態(tài)—{0}", task2.Status);Thread.Sleep(2000); Console.WriteLine();Console.WriteLine(" ---------------3-----------——");IAsyncResult r = taskDele.BeginInvoke(out threadId, Callback, "在線程池中異步調用回調函數(shù)");Task<string> task3 = Task<string>.Factory.FromAsync(r,_=> taskDele.EndInvoke(out threadId,r));task2.ContinueWith(t => Console.WriteLine("task3 回調函數(shù)執(zhí)行結束,執(zhí)行后續(xù)子操作:{0},線程ID:{1}", t.Result,threadId));while (!task2.IsCompleted){Console.WriteLine(" task3狀態(tài)——{0}", task2.Status);Thread.Sleep(500);}Console.WriteLine(" ——task3狀態(tài)—{0}", task2.Status);Thread.Sleep(2000);Console.WriteLine(" --------------------------——"); Thread.Sleep(2000);Console.Read(); }private static void Callback(IAsyncResult r){Console.WriteLine("開始調用回調函數(shù)。。。");Console.WriteLine("回調函數(shù)此時的狀態(tài) :{0}", r.AsyncState);Console.WriteLine("調用此回調函數(shù)的線程是否在線程池 :{0}", Thread.CurrentThread.IsThreadPoolThread);Console.WriteLine("調用此回調函數(shù)的線程在線程池在的ID :{0}", Thread.CurrentThread.ManagedThreadId);}private static string RunTask(string name){Console.WriteLine("開始工作。。。"); Console.WriteLine("調用此回調函數(shù)的線程是否在線程池 :{0}", Thread.CurrentThread.IsThreadPoolThread);Thread.Sleep(TimeSpan.FromSeconds(2));Thread.CurrentThread.Name = name;int threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("此線程的ID :{0},名稱{1}", threadId, Thread.CurrentThread.Name);}private static string RunTask(out int threadId){Console.WriteLine("開始工作。。。");Console.WriteLine("調用此回調函數(shù)的線程是否在線程池 :{0}", Thread.CurrentThread.IsThreadPoolThread);Thread.Sleep(TimeSpan.FromSeconds(2));threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("此線程在線程池在的ID :{0}", threadId);}} }

?

?

?2.程序運行結果如下圖。

?

?????? 程序運行結果中可以看出來,task1中直接傳入了IAsyncResult和Func< IAsyncResult,string>,task1執(zhí)行委托的異步調用,正常。

?

??????? Task2與task1類似,只是使用了不同的FromAsync的方法重載,這個重載不允許指定一個將會在異步調用完成之后被調用的回調函數(shù)。我們在示例中使用后續(xù)操作代替了回調函數(shù)。如果必須使用回調函數(shù),可以使用類似task1的調用方式。

?

??????? Task3我們通過一個技巧實現(xiàn)了調用與FromAsync不兼容的委托。我們通過將EndInvoke封裝到一個lambda表達式中,從而適應FromAsync方法。

?

?

?

五、?? 將EAP模式轉換為任務

?

?????? 本示例,將上一篇(多線程編程學習筆記——線程池(三))中的(使用BackgroundWorker組件示例)轉為任務。

??????? 本示例是學習如何基于事件的異步轉換為TASK來運行。本示例的關鍵是使用TaskCompletionSource<T>,T是異步操作結果的類型。

?

using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ThreadPoolDemo{ class Program{ static void Main(string[] args){Console.WriteLine(" 將EAP模式轉為Task。。。");var tcs = new TaskCompletionSource<int>();var worker = new BackgroundWorker();worker.DoWork += (sender, eventArgs) =>{eventArgs.Result = RunTask("后臺線程 1 ", 5);};worker.RunWorkerCompleted += (sender, eventArgs) =>{if (eventArgs.Error!=null){Console.WriteLine(" ——出錯—{0}", eventArgs.Error);tcs.SetException(eventArgs.Error);}elseif (eventArgs.Cancelled){Console.WriteLine(" ——取消—");tcs.SetCanceled();//取消 }else{Console.WriteLine(" ——設置結果值—{0}", eventArgs.Result);tcs.SetResult((int)eventArgs.Result);} };worker.RunWorkerAsync();int result = tcs.Task.Result;Console.WriteLine(" ——任務Task運行結果—{0}", result);Thread.Sleep(2000); Console.Read();} private static int RunTask(string name,int seconds){Console.WriteLine("Task {0} 運行在線程={1}中,是否在線程池 :{2}",name, Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread);Thread.Sleep(TimeSpan.FromSeconds(seconds));
return 42 * seconds;}} }

?

2.程序運行結果如下圖。

?

?

?

????? 注:tcs.SetResult要封閉在try-catch中,以方便獲取異常。或者可以使用tcs.TrySetResult。

?

總結

以上是生活随笔為你收集整理的多线程编程学习笔记——任务并行库(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。