溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C#線程完成數(shù)實(shí)例分析

發(fā)布時(shí)間:2022-02-14 09:25:25 來源:億速云 閱讀:124 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“C#線程完成數(shù)實(shí)例分析”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“C#線程完成數(shù)實(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}完成一件事了");
        }
    }

示例很簡單,每個(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)行重試

感謝各位的閱讀,以上就是“C#線程完成數(shù)實(shí)例分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)C#線程完成數(shù)實(shí)例分析這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI