您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“C#多線程之Parallel類怎么用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“C#多線程之Parallel類怎么用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
Parallel類是對線程的一個抽象。該類位于System.Threading.Tasks名稱空間中,提供了數據和任務并行性。
Paraller類定義了數據并行地For和ForEach的靜態方法,以及任務并行的Invoke的靜態方法。Parallel.For()和Parallel.ForEach()方法在每次迭代中調用相同的代碼,Paraller.Invoke()允許調用不同的方法。
Parallel.For()方法類似C#語法的for循環語句,多次執行一個任務。但該方法并行運行迭代,迭代的順序沒有定義。
Parallel.For()方法中,前兩個參數定義了循環的開頭和結束,第三個參數是一個Action委托。Parallel.For方法返回類型是ParallelLoopResult結構,它提供了循環是否結束的信息。
Parallel.For有多個重載版本和多個泛型重載版本。
示例:
static void ForTest() { ParallelLoopResult plr = Parallel.For(0,10,i => { Console.WriteLine("{0},task:{1},thread:{2}",i,Task.CurrentId,Thread.CurrentThread.ManagedThreadId); Thread.Sleep(5000); }); if (plr.IsCompleted) Console.WriteLine("completed!"); }
輸出:
任務不一定映射到一個線程上。線程也可以被不同的任務重用。
上面的例子,使用了.NET 4.5中新增的Thread.Sleep方法,而不是Task.Delay方法。Task.Delay是一個異步(http://www.cnblogs.com/afei-24/p/6757361.html)方法,用于釋放線程供其它任務使用。
示例:
static void ForTestDelay() { ParallelLoopResult plr = Parallel.For(0, 10,async i => { Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); }); if (plr.IsCompleted) Console.WriteLine("completed!"); Console.ReadKey(); }
輸出:
上面代碼使用了await關鍵字進行延遲,輸出結果顯示延遲前后的代碼運行在不同的線程中。而且延遲后的任務不再存在,只留下線程,這里還重用了前面的線程。另一個重要的方面是,Parallel類的For方法并沒有等待延遲,而是直接完成。parallel類只等待它創建的任務,而不等待其它后臺活動。所以上面代碼使用了Console.ReadKey();使主線程一直運行,不然很可能看不到后面的輸出。
For()方法的一個重載版本接受第三個Action<int,ParallelLoopState>委托類型的參數。使用這個方法可以調用ParallelLoopState的Break()或Stop()方法,以停止循環。
注意,前面說到,迭代的順序是沒有定義的。
示例:
static void ForStop() { ParallelLoopResult plr = Parallel.For(0,10,(int i,ParallelLoopState pls)=> { Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); if (i > 5) pls.Break(); }); Console.WriteLine("is completed:{0}",plr.IsCompleted); Console.WriteLine("最低停止索引:{0}",plr.LowestBreakIteration); }
輸出:
迭代值在大于5時中斷,但其它已開始的任務同時執行。
Parallel.For方法使用多個線程來執行循環,如果需要對每個線程進行初始化,就可以使用Parallel.For<TLocal>()方法。除了from和to對應的值之外,Parallel.For方法的泛型版本還接受3個委托參數:
第一個委托參數的類型是Func<TLocal>,這個方法僅對用于執行迭代的每個線程調用每一次。
第二個委托參數為循環體定義了委托。該參數類型是Func<int, ParallelLoopState, TLocal, TLocal>。其中第一個參數是循環迭代,第二個參數ParallelLoopState允許停止循環,第三個參數接受從上面參數委托Func<TLocal>返回的值,該委托還需返回一個TLocal類型的值。該方法對每次迭代調用。
第三個委托參數指定一個委托Action<TLocal>,接受第二個委托參數的返回值。這個方法僅對用于執行迭代的每個線程調用每一次。
示例:
static void ForInit() { ParallelLoopResult plr = Parallel.For(0,10,()=> { Console.WriteLine("init thread:{0},task:{1}",Thread.CurrentThread.ManagedThreadId,Task.CurrentId); return Thread.CurrentThread.ManagedThreadId.ToString(); }, (i, pls,strInit)=> { Console.WriteLine("body:{0},strInit:{1},thraed:{2},task:{3}",i,strInit,Thread.CurrentThread.ManagedThreadId,Task.CurrentId); return i.ToString(); }, (strI)=> { Console.WriteLine("finally {0}",strI); }); }
輸出:
Parallel.ForEach方法遍歷實現了IEnumerable的集合,類似于foreach,但以異步方式遍歷。沒有確定遍歷順序。
示例:
static void ForeachTest() { string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" }; ParallelLoopResult plr = Parallel.ForEach<string>(data, s => { Console.WriteLine(s); }); if (plr.IsCompleted) Console.WriteLine("completed!"); }
如果需要中斷,可以使用ForEach的重載版本和參數ParallelLoopState。
訪問索引器:
ParallelLoopResult plr1 = Parallel.ForEach<string>(data, (s,pls,l) => { Console.WriteLine("data:{0},index:{1}",s,l); });
如果多個任務并行運行,可以使用Parallel.Invoke方法。該方法允許傳遞一個Action委托數組。
static void ParallerInvoke() { Action[] funs = { Fun1,Fun2}; Parallel.Invoke(funs); } static void Fun1() { Console.WriteLine("f1"); Console.WriteLine("task:{0},thread:{1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); } static void Fun2() { Console.WriteLine("f2"); Console.WriteLine("task:{0},thread:{1}", Task.CurrentId, Thread.CurrentThread.ManagedThreadId); }
讀到這里,這篇“C#多線程之Parallel類怎么用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。