C#如何使用Task類解決線程的等待問題
使用Task類解決線程的等待問題
在任何的編程語言中,面對耗時任務(wù)時,我們都會有這樣的需求:讓任務(wù)執(zhí)行一定時間,主任務(wù)進行等待,如果到時仍然完成不了,那么就不再等待。
比如一個常見的應(yīng)用就是連接遠程數(shù)據(jù)庫,如果由于網(wǎng)絡(luò)問題連接不上,那么只等待指定時間如3秒,然后就不再等待。
這樣的代碼如果自己寫類來實現(xiàn)的話并不困難,然而實際上C#已經(jīng)內(nèi)置了Task類用于解決此問題。
Task類
Task是C#中專門用于接收任務(wù)的類,通過構(gòu)造函數(shù)接收任務(wù),使用start()方法啟動。當任務(wù)啟動以后,可以使用Task.WaitAll(Task[] tasks, int timeout) 等待所有任務(wù)完成后或時間到 timeout ms后再繼續(xù)。
注:由于Task的構(gòu)造函數(shù)接受的是Action委托,所以是沒有返回值的。
用法
Task核心功能是代理一個方法,然后在啟動,主線程可以指定等待時間,具體如以下代碼所示。
// 1. 初始化任務(wù) var t1 = new Task(() => { ?? ??? ?Thread.Sleep(2000); ?? ??? ?Console.WriteLine("Hello"); ?? ?}); ? // 2. 啟動任務(wù)?? ? t1.start(); // 3. 指定等等時間,單位為毫秒 Task.WaitAll(new Task[] { t1 }, 3000); ?
示例
在本示例中,我們啟動了一個簡單的任務(wù)t1,會暫時2秒然后輸出字符串“Hello”,然后主線程等待3000毫秒,代碼如下所示:
void Test1() { ?? ?//定義一個任務(wù),等待2秒后輸出Hello? ?? ?var t1 = new Task(() => { ?? ??? ?Thread.Sleep(2000); ?? ??? ?Console.WriteLine("Hello"); ?? ?}); ? ? ??? ?// 以多線程方式啟動任務(wù),t1和當前線程是兩個線程 ?? ?t1.Start();? ?? ?Console.WriteLine("t1 started."); ?? ?//等待所有任務(wù)結(jié)束(這里只有t1),程序會卡在這里。等待的時間為 3000 毫秒 ?? ?Console.WriteLine("waiting..."); ?? ?Task.WaitAll(new Task[] { t1 }, 3000); ? ?? ?Console.WriteLine("stop waiting.") ?? ?// 判斷t1任務(wù)是否完成 ?? ?if (!t1.IsCompleted) ?? ??? ?Console.WriteLine("Running..."); ?? ?Console.WriteLine("Task done."); }?? ??? ??? ? void print(string msg) { ?? ?Console.WriteLine($"{DateTime.Now:HH:mm:ss.ffff} {msg}"); }
程序運行后輸出以下結(jié)果:
14:51:54.2233 t1 started.
14:51:54.2457 waiting...
14:51:56.2456 Hello
14:51:56.2456 stop waiting.
14:51:56.2456 Task done.
可以看到,程序在等待后約2000毫秒,任務(wù)t1執(zhí)行完成,輸出 Hello,但是由于我們設(shè)置的等待時間是3000毫秒,所以主線程仍然在等待中。在經(jīng)過了約3000毫秒后,程序停止等待,繼續(xù)執(zhí)行。在繼續(xù)執(zhí)行時,由于t1已經(jīng)執(zhí)行完成,所以沒有輸出繼續(xù)執(zhí)行的相關(guān)信息。
下面我們將上面的等待時間由3000毫秒改為1000毫秒,那么在執(zhí)行以后結(jié)果如下所示:
14:48:36.9624 t1 started.
14:48:36.9848 waiting...
14:48:37.9755 stop waiting.
14:48:37.9755 t1 still running...
14:48:37.9755 Task done.
14:48:38.9860 Hello
由以上結(jié)果可見,程序在等待了約1000毫秒后,由于等待時間已經(jīng)到了,就繼續(xù)向前執(zhí)行,此時 t1 并沒有執(zhí)行完成,所以會輸出 “t1 still running…”。等主線程執(zhí)行完以后,t1 最終執(zhí)行完成,輸出了Hello。
小結(jié)
由以上示例可見,Task能夠很方便的啟動一個任務(wù),主線程也可以決定等待時間。
不過這里還有三點需要注意一下:
1)Task沒有返回值;
2)主線程不能中止Task;
3)計時精度不高,有一定的誤差。
基于以上問題,我們可以知道Task類合適用在一些對控制和計時精度要求不高的場合。
C#代碼執(zhí)行中等待10秒
//等待10秒 DateTime dt1 = DateTime.Now; while ((DateTime.Now - dt1).TotalMilliseconds < 10000) { continue; };
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#如何Task執(zhí)行任務(wù),等待任務(wù)完成
這篇文章主要介紹了C#如何Task執(zhí)行任務(wù),等待任務(wù)完成,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06C#基于時間輪調(diào)度實現(xiàn)延遲任務(wù)詳解
在很多.net開發(fā)體系中開發(fā)者在面對調(diào)度作業(yè)需求的時候一般會選擇三方開源成熟的作業(yè)調(diào)度框架來滿足業(yè)務(wù)需求,但是有些時候可能我們只是需要一個簡易的延遲任務(wù)。本文主要分享一個簡易的基于時間輪調(diào)度的延遲任務(wù)實現(xiàn),需要的可以參考一下2022-12-12