接上文 多線程編程學習筆記——任務並行庫(一)html
接上文 多線程編程學習筆記——任務並行庫(二)編程
接上文 多線程編程學習筆記——任務並行庫(三)windows
8、 並行運行任務數組
本示例學習如何同時運行多個任務,而且當任務所有完成或其中一個完成時,如何高效的獲得通知。多線程
1.示例代碼異步
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(" 處理並行Task。。。。。"); var task1 = new Task<int>(() => RunTask("任務 1", 3)); var task2 = new Task<int>(() => RunTask("任務 2", 2)); var whenTaskAll = Task.WhenAll(task1, task2); whenTaskAll.ContinueWith(t => Console.WriteLine(" ——task1 結果值={0}---task2 結果值={1}",t.Result[0],t.Result[1]),
TaskContinuationOptions.OnlyOnRanToCompletion); task1.Start(); task2.Start(); Thread.Sleep(5000); Console.WriteLine(" ——————————————————————"); var tasks = new List<Task<int>>(); for (int i = 3; i < 10; i++) { int cnt = i; var task = new Task<int>(() => RunTask(string.Format("任務 {0}",cnt), cnt)); tasks.Add(task); task.Start(); } while(tasks.Count>0) { var completedTask = Task.WhenAny(tasks).Result; tasks.Remove(completedTask); Console.WriteLine(" ——一個task 完成任務—結果值={0}", completedTask.Result); } Thread.Sleep(7000); 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 20 * seconds; } } }
2。程序運行結果。以下圖。post
當程序啓動時,建立了兩個任務(task1,task2),而後用task.whenall方法建立了第三個任務,這個任務會在全部任務完成以後運行。這個任務的結果提供了一個數組,第一個元素是第一個任務的結果,第二個元素是第二個任務的結果,以此類推。學習
而後咱們建立了一個任務列表,列表中有七個任務,而後使用task.whenany方法,等這一系列任務中的任何一個任務完成 ,就從列表中移除,並繼續等待其餘任務完成,直到列表爲空。this
9、 使用taskScheduler配置任務的執行url
咱們學習任務調度程序,經過異步代碼與UI進行交互。因此本示例是建立Windows應用程序。
taskScheduler是負責如何執行任務,默認狀況下是把task放入線程池中的工做線程中。
1.在visual studio 中建立一個windowsForm個界面,名稱爲FormTPL 。這個界面中有同步,異步兩個按鈕。
2.程序界面以下圖。
3.代碼以下。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace ThreadTPLDemo { public partial class FormTPL : Form { public FormTPL() { InitializeComponent(); } private void buttonSync_Click(object sender, EventArgs e) { try { string result = RunTask().Result; textBoxMsg.Text = result; } catch (Exception ex) { textBoxMsg.Text = ex.Message; } } private void buttonAsync_Click(object sender, EventArgs e) { this.Cursor = Cursors.WaitCursor; Task<string> task = RunTask(); task.ContinueWith(t => { textBoxMsg.Text = t.Exception.InnerException.Message; this.Cursor = Cursors.Arrow; }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,TaskScheduler.FromCurrentSynchronizationContext()); } private void buttonAsyncOk_Click(object sender, EventArgs e) { this.Cursor = Cursors.WaitCursor; Task<string> task = RunTask(TaskScheduler.FromCurrentSynchronizationContext()); task.ContinueWith(t =>this.Cursor=Cursors.Arrow, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext()); } private Task<string> RunTask() { return RunTask(TaskScheduler.Default); } private Task<string> RunTask(TaskScheduler tsched) { Task delay = Task.Delay(TimeSpan.FromSeconds(5)); return delay.ContinueWith(t => { string str = string.Format("Task 運行在線程={0},是不是在線程池中運行:{1}",Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread); textBoxMsg.Text = str; return str; },tsched); } } }
4。程序運行結果中會出現第一個問題,當點擊同步按鈕,執行程序時,整個應用 程序的用戶界面假死,沒法進行其餘的任務操做。以下圖。從圖中2處能夠看出「異步交互」按鈕沒法顯示。
5. 解決同步執行界面會假死的問題,咱們使用異步執行的方式解決。
6. 第二個問題,並且當咱們從線程中直接訪問UI界面中的控件時,會拋出異常。
7. 當咱們按第三個按鈕,而後執行代碼,程序正常運行,並獲得結果。以下圖。
最後,本人不建議使用taskScheduler來開發任務調度程序,建議使用Quartz.Net來開發任務調度程序。