<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
假如,程式需要向一個 Web 傳送 5 次請求,受網路波動影響,有一定機率請求失敗。如果失敗了,就需要重試。
範例程式碼如下:
class Program { private static int count = 0; static void Main(string[] args) { for (int i = 0; i < 5; i++) new Thread(HttpRequest).Start(); // 建立執行緒 // 用於不斷向另一個執行緒傳送訊號 while (count < 5) { Thread.Sleep(100); } Console.WriteLine("任務執行完畢"); } // 模擬網路請求 public static void HttpRequest() { Console.WriteLine("開始一個任務"); // 隨機生成一個數,如果為偶數,則模擬請求失敗 bool isSuccess = (new Random().Next(0, 10)) % 2 == 0; // ... ...模擬請求 HTTP Thread.Sleep(TimeSpan.FromSeconds(2)); // 請求失敗則重試 if (!isSuccess) { Console.WriteLine($"請求失敗,count={count}"); new Thread(() => { HttpRequest(); }).Start(); return; } // 完成一次任務,+1 Interlocked.Add(ref count,1); Console.WriteLine($"完成任務,count={count}"); } }
程式碼太糟糕了,但我們可以使用 CountdownEvent 類來改造它。
表示在計數變為零時處於有訊號狀態的同步基元。
也就是說,設定一個計數器,每個執行緒完成後,就會減去 1 ,當計數器為 0 時,代表所有執行緒都已經完成了任務。
CountdownEvent 類別建構函式如下:
建構函式 | 說明 |
---|---|
CountdownEvent(Int32) | 使用指定計數初始化 CountdownEvent 類的新範例。 |
CountdownEvent 類的常用方法如下:
方法 | 說明 |
---|---|
AddCount() | 將 CountdownEvent 的當前計數加 1。 |
AddCount(Int32) | 將 CountdownEvent 的當前計數增加指定值。 |
Reset() | 將 CurrentCount 重置為 InitialCount 的值。 |
Reset(Int32) | 將 InitialCount 屬性重新設定為指定值。 |
Signal() | 向 CountdownEvent 註冊訊號,同時減小 CurrentCount 的值。 |
Signal(Int32) | 向 CountdownEvent 註冊多個訊號,同時將 CurrentCount 的值減少指定數量。 |
TryAddCount() | 增加一個 CurrentCount 的嘗試。 |
TryAddCount(Int32) | 增加指定值的 CurrentCount 的嘗試。 |
Wait() | 阻止當前執行緒,直到設定了 CountdownEvent 為止。 |
Wait(CancellationToken) | 阻止當前執行緒,直到設定了 CountdownEvent 為止,同時觀察 CancellationToken。 |
Wait(Int32) | 阻止當前執行緒,直到設定了 CountdownEvent 為止,同時使用 32 位帶符號整數測量超時。 |
Wait(Int32, CancellationToken) | 阻止當前執行緒,直到設定了 CountdownEvent 為止,並使用 32 位帶符號整數測量超時,同時觀察 CancellationToken。 |
Wait(TimeSpan) | 阻止當前執行緒,直到設定了 CountdownEvent 為止,同時使用 TimeSpan 測量超時。 |
Wait(TimeSpan, CancellationToken) | 阻止當前執行緒,直到設定了 CountdownEvent 為止,並使用 TimeSpan 測量超時,同時觀察 CancellationToken。 |
API 比較多,沒事,我們來慢慢了解它。
我們來編寫一個場景程式碼,一個有五件事,需要完成,分別派出 5 個人去實現。
.Wait();
用在一個執行緒中,這個執行緒將等待其它完成都完成任務後,才能繼續往下執行。
Signal();
用於工作執行緒中,向 CountdownEvent 物件傳送訊號,告知執行緒已經完成任務,然後 CountdownEvent.CurrentCount
將減去 1。
當計數器為 0 時,阻塞的執行緒將恢復執行。
程式碼範例如下:
class Program { // 手頭上有 5 件事 private static CountdownEvent countd = new CountdownEvent(5); static void Main(string[] args) { Console.WriteLine("開始交待任務"); // 同時叫 5 個人,去做 5 件事 for (int i = 0; i < 5; i++) { Thread thread = new Thread(DoOne); thread.Name = $"{i}"; thread.Start(); } // 等他們都完成事情 countd.Wait(); Console.WriteLine("任務完成,執行緒退出"); 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}完成一件事了"); } }
範例很簡單,每個執行緒在完成自己的任務時,需要呼叫 Signal()
方法,使得計數器減去1。
.Wait();
可以等待所有的任務完成。
需要注意的是,如果不呼叫 Signal()
或者計數器一直不為0,那麼 Wait()
將無限等待。
當然,Wait()
可以設定等待時間,
另外我們也看到了常用方法中有 AddCount()
、Reset()
等。
這個類的等待控制方式比較寬鬆,Wait()
後,到底什麼時候才能執行,全憑其它執行緒自覺。
如果發現執行緒執行任務失敗,我們可以不呼叫 Signal()
或者 使用 AddCount()
來增加次數,進行重試
到此這篇關於C#多執行緒系列之執行緒完成數的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45