C# 中的 Thread.Sleep()
在本指南中,我們將瞭解為什麼在 C# 中使用 thread.sleep()
被認為是有害的,以及為什麼不應該使用這種特殊方法。
使用 thread.sleep()
會發生什麼?有沒有替代方法?
找出本指南中的所有內容。讓我們深入瞭解一下。
為什麼 thread.sleep()
在 C#
中是有害的
要理解 thread.sleep()
為何有害,我們必須瞭解此方法背後的工作。好吧,在 C# 中,sleep
方法有其用途。
你可以使用它在特定時間段內暫停或暫停當前功能(執行緒執行)。我們可以通過以毫秒為單位的時間來暫停執行緒執行一段時間。
我們還可以使用 TimeSpan
屬性,如下面的程式碼所示。
// Time in milliseconds
Thread.Sleep(5000);
Or
// Time in hours, minutes, seconds
TimeSpan tsObj = new TimeSpan(0, 0, 5);
Thread.Sleep(tsObj);
現在,上述兩種方法都會停止程式五秒鐘。這意味著,通過上面的程式碼,我們試圖將執行緒掛起 1 秒。
但是,這一切的意義何在?讓我們瞭解它的工作原理。
thread.sleep()
如何在 C#
中工作
我們都知道一個程式逐行執行,這意味著整個程式同步執行,一行接一行。有時,在程式設計過程中,我們需要執行一項需要一些時間才能完成的任務。
例如,從 API 獲取資料,我們可以使用 sleep
函式讓它等待,從 API 獲取資料,然後執行程式的其餘部分。這是必要的,但卻是一種非常有害和糟糕的方法。
例如,我們試圖獲取的資料可能很大並且需要時間。我們的程式將在此期間停止;這不是一個理想的方法。
Thread.Sleep(n)
意味著在 n
毫秒內儘可能多的時間片(也稱為執行緒量子)停止正在執行的執行緒。時間片的持續時間取決於 Windows 的版本/型別和使用的處理器,但通常持續 15 到 30 毫秒。
這表明執行緒可能會阻塞超過 n
毫秒。你的執行緒不太可能在 n
毫秒後精確地重新喚醒。
因此,Thread.Sleep
在計時方面沒有任何作用。
執行緒是一種有限資源,需要大約 200,000 次迴圈建立和 100,000 次迴圈銷燬。預設情況下,他們為每個上下文轉換使用 2,000–8,000 個週期,併為他們的堆疊保留 1 兆位元組的虛擬記憶體。
什麼是替代方法
我們有時需要延遲我們的執行緒以使程式完美執行。如上所述,我們可能需要獲取一些 API 資料,這需要時間。
但是因為它而停止整個程式是一種不好的方法。那麼,我們該如何避免呢?
讓我們向你介紹非同步程式設計。
非同步程式設計
C# 中的 async
和 await
關鍵字有助於使非同步程式設計在當今變得非常普遍。整個應用程式在使用 UI 時將不得不等待完成操作並使用需要很長時間的長時間執行的方法,例如讀取一個巨大的檔案或單擊一個按鈕。
換句話說,如果同步應用程式中的任何程序被阻塞,整個應用程式也會停止,我們的應用程式將停止執行,直到整個任務完成。
在這種情況下,非同步程式設計非常有用。通過採用非同步程式設計,應用程式可以繼續執行不依賴於完成的任務。
藉助 async
和 await
關鍵字,我們將以更少的工作實現傳統非同步程式設計的所有優點。
同時執行兩個方法(C# 中的 async
和 await
關鍵字)
假設我們有兩個方法,FirstMethod()
和 SecondMethod()
,它們彼此獨立,並且 FirstMethod()
需要很長時間才能執行其任務。
同步程式設計從 FirstMethod()
開始並等待它完成,然後再繼續執行 SecondMethod()
。即使這兩個過程是獨立的,這個過程也會花費很多時間。
我們可以通過使用簡單的執行緒程式設計同時執行所有功能,但這會在我們等待任務完成時阻塞使用者介面。在傳統的程式設計中,我們需要編寫大量的程式碼來解決這個問題,但是如果我們使用 async
和 await
關鍵字,我們可以用更少的程式碼解決這個問題。
我們還將看到其他示例,在這些情況下,當 SecondMethod()
依賴於 FirstMethod()
時,它將使用 await
關鍵字等待 FirstMethod()
完成執行。
在 C# 中,async
和 await
是程式碼標記,用於指示當任務完成時控制元件應返回的位置。
從真實世界的示例開始將幫助你更好地理解它們背後的程式設計。看看下面的程式碼。
class Program {
static void Main(string[] args) {
FirstMethod();
SecondMethod();
Console.ReadKey();
}
public static async Task FirstMethod() {
await Task.Run(() => {
for (int i = 0; i < 100; i++) {
Console.WriteLine(" First Method");
// Do something
Task.Delay(100).Wait();
}
});
}
public static void SecondMethod() {
for (int i = 0; i < 25; i++) {
Console.WriteLine(" Second Method ");
// Do something
Task.Delay(100).Wait();
}
}
}
上述程式碼的輸出將如下所示。
First Method
Second Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
First Method
Second Method
Second Method
Second Method
Second Method
Second Method
正如你在上面的程式碼中看到的那樣,整個程式不會因為我們必須停止執行一個執行緒而停止。它們都可以使用非同步程式設計同時執行。
假設你在某個時刻必須獲取一些 API 資料,這需要時間。因此,程式將在沒有獲取資料的情況下移動到下一行,因此我們需要稍微延遲一下以獲取該資料,然後再移動到下一行。
Haider specializes in technical writing. He has a solid background in computer science that allows him to create engaging, original, and compelling technical tutorials. In his free time, he enjoys adding new skills to his repertoire and watching Netflix.
LinkedIn