C#多線程系列之線程完成數(shù)
解決一個(gè)問題
假如,程序需要向一個(gè) Web 發(fā)送 5 次請(qǐng)求,受網(wǎng)路波動(dòng)影響,有一定幾率請(qǐng)求失敗。如果失敗了,就需要重試。
示例代碼如下:
class Program { private static int count = 0; static void Main(string[] args) { for (int i = 0; i < 5; i++) new Thread(HttpRequest).Start(); // 創(chuàng)建線程 // 用于不斷向另一個(gè)線程發(fā)送信號(hào) while (count < 5) { Thread.Sleep(100); } Console.WriteLine("任務(wù)執(zhí)行完畢"); } // 模擬網(wǎng)絡(luò)請(qǐng)求 public static void HttpRequest() { Console.WriteLine("開始一個(gè)任務(wù)"); // 隨機(jī)生成一個(gè)數(shù),如果為偶數(shù),則模擬請(qǐng)求失敗 bool isSuccess = (new Random().Next(0, 10)) % 2 == 0; // ... ...模擬請(qǐng)求 HTTP Thread.Sleep(TimeSpan.FromSeconds(2)); // 請(qǐng)求失敗則重試 if (!isSuccess) { Console.WriteLine($"請(qǐng)求失敗,count={count}"); new Thread(() => { HttpRequest(); }).Start(); return; } // 完成一次任務(wù),+1 Interlocked.Add(ref count,1); Console.WriteLine($"完成任務(wù),count={count}"); } }
代碼太糟糕了,但我們可以使用 CountdownEvent 類來改造它。
CountdownEvent 類
表示在計(jì)數(shù)變?yōu)榱銜r(shí)處于有信號(hào)狀態(tài)的同步基元。
也就是說,設(shè)定一個(gè)計(jì)數(shù)器,每個(gè)線程完成后,就會(huì)減去 1 ,當(dāng)計(jì)數(shù)器為 0 時(shí),代表所有線程都已經(jīng)完成了任務(wù)。
構(gòu)造函數(shù)和方法
CountdownEvent 類的構(gòu)造函數(shù)如下:
構(gòu)造函數(shù) | 說明 |
---|---|
CountdownEvent(Int32) | 使用指定計(jì)數(shù)初始化 CountdownEvent 類的新實(shí)例。 |
CountdownEvent 類的常用方法如下:
方法 | 說明 |
---|---|
AddCount() | 將 CountdownEvent 的當(dāng)前計(jì)數(shù)加 1。 |
AddCount(Int32) | 將 CountdownEvent 的當(dāng)前計(jì)數(shù)增加指定值。 |
Reset() | 將 CurrentCount 重置為 InitialCount 的值。 |
Reset(Int32) | 將 InitialCount 屬性重新設(shè)置為指定值。 |
Signal() | 向 CountdownEvent 注冊(cè)信號(hào),同時(shí)減小 CurrentCount 的值。 |
Signal(Int32) | 向 CountdownEvent 注冊(cè)多個(gè)信號(hào),同時(shí)將 CurrentCount 的值減少指定數(shù)量。 |
TryAddCount() | 增加一個(gè) CurrentCount 的嘗試。 |
TryAddCount(Int32) | 增加指定值的 CurrentCount 的嘗試。 |
Wait() | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止。 |
Wait(CancellationToken) | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止,同時(shí)觀察 CancellationToken。 |
Wait(Int32) | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止,同時(shí)使用 32 位帶符號(hào)整數(shù)測(cè)量超時(shí)。 |
Wait(Int32, CancellationToken) | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止,并使用 32 位帶符號(hào)整數(shù)測(cè)量超時(shí),同時(shí)觀察 CancellationToken。 |
Wait(TimeSpan) | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止,同時(shí)使用 TimeSpan 測(cè)量超時(shí)。 |
Wait(TimeSpan, CancellationToken) | 阻止當(dāng)前線程,直到設(shè)置了 CountdownEvent 為止,并使用 TimeSpan 測(cè)量超時(shí),同時(shí)觀察 CancellationToken。 |
API 比較多,沒事,我們來慢慢了解它。
示例
我們來編寫一個(gè)場(chǎng)景代碼,一個(gè)有五件事,需要完成,分別派出 5 個(gè)人去實(shí)現(xiàn)。
.Wait();
用在一個(gè)線程中,這個(gè)線程將等待其它完成都完成任務(wù)后,才能繼續(xù)往下執(zhí)行。
Signal();
用于工作線程中,向 CountdownEvent 對(duì)象發(fā)送信號(hào),告知線程已經(jīng)完成任務(wù),然后 CountdownEvent.CurrentCount
將減去 1。
當(dāng)計(jì)數(shù)器為 0 時(shí),阻塞的線程將恢復(fù)執(zhí)行。
代碼示例如下:
class Program { // 手頭上有 5 件事 private static CountdownEvent countd = new CountdownEvent(5); static void Main(string[] args) { Console.WriteLine("開始交待任務(wù)"); // 同時(shí)叫 5 個(gè)人,去做 5 件事 for (int i = 0; i < 5; i++) { Thread thread = new Thread(DoOne); thread.Name = $"{i}"; thread.Start(); } // 等他們都完成事情 countd.Wait(); Console.WriteLine("任務(wù)完成,線程退出"); Console.ReadKey(); } public static void DoOne() { int n = new Random().Next(0, 10); // 模擬要 n 秒才能完成 Thread.Sleep(TimeSpan.FromSeconds(n)); // 完成了,減去一件事 countd.Signal(); Console.WriteLine($" {Thread.CurrentThread.Name}完成一件事了"); } }
示例很簡(jiǎn)單,每個(gè)線程在完成自己的任務(wù)時(shí),需要調(diào)用 Signal()
方法,使得計(jì)數(shù)器減去1。
.Wait();
可以等待所有的任務(wù)完成。
需要注意的是,如果不調(diào)用 Signal()
或者計(jì)數(shù)器一直不為0,那么 Wait()
將無限等待。
當(dāng)然,Wait()
可以設(shè)置等待時(shí)間,
另外我們也看到了常用方法中有 AddCount()
、Reset()
等。
這個(gè)類的等待控制方式比較寬松,Wait()
后,到底什么時(shí)候才能執(zhí)行,全憑其它線程自覺。
如果發(fā)現(xiàn)線程執(zhí)行任務(wù)失敗,我們可以不調(diào)用 Signal()
或者 使用 AddCount()
來增加次數(shù),進(jìn)行重試
到此這篇關(guān)于C#多線程系列之線程完成數(shù)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- C#多線程系列之工作流實(shí)現(xiàn)
- C#多線程系列之任務(wù)基礎(chǔ)(三)
- C#多線程系列之任務(wù)基礎(chǔ)(二)
- C#多線程系列之任務(wù)基礎(chǔ)(一)
- C#多線程系列之線程池
- C#多線程系列之線程等待
- C#多線程系列之讀寫鎖
- C#多線程系列之多階段并行線程
- C#多線程系列之手動(dòng)線程通知
- C#多線程系列之線程通知
- C#多線程系列之資源池限制
- C#多線程系列之進(jìn)程同步Mutex類
- C#多線程系列之原子操作
- C#多線程系列之多線程鎖lock和Monitor
- C#多線程系列之線程的創(chuàng)建和生命周期
- C#多線程系列之a(chǎn)sync和await用法詳解
相關(guān)文章
VsCode使用EmmyLua插件調(diào)試Unity工程Lua代碼的詳細(xì)步驟
這篇文章主要介紹了VsCode使用EmmyLua插件調(diào)試Unity工程Lua代碼,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08C#中Request.Cookies 和 Response.Cookies 的區(qū)別分析
本文通過實(shí)例代碼向我們展示了C#中Request.Cookies 和 Response.Cookies 的區(qū)別,文章淺顯易懂,這里推薦給大家。2014-11-11詳解C# TimeSpan 計(jì)算時(shí)間差(時(shí)間間隔)
本篇文章主要介紹了C# TimeSpan 計(jì)算時(shí)間差(時(shí)間間隔),非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例分享
這篇文章主要介紹了使用c#判斷網(wǎng)絡(luò)連接狀態(tài)的示例,需要的朋友可以參考下2014-02-02