[英]What is the impact of Thread.Sleep(1) in C#?
在 Windows 窗體應用程序中,調用Thread.Sleep(1)
的影響是什么,如以下代碼所示:
public Constructor()
{
Thread thread = new Thread(Task);
thread.IsBackground = true;
thread.Start();
}
private void Task()
{
while (true)
{
// do something
Thread.Sleep(1);
}
}
這個線程會占用所有可用的 CPU 嗎?
我可以使用哪些分析技術來測量此線程的 CPU 使用率(任務管理器除外)?
如上所述,您的循環不會占用 CPU。
但請注意:Windows不是實時操作系統,因此您不會從 Thread.Sleep(1) 獲得每秒 1000 次喚醒。 如果您沒有使用timeBeginPeriod設置您的最小分辨率,您將每 15 毫秒喚醒一次。 即使您將最小分辨率設置為 1 毫秒,您仍然只能每 3-4 毫秒喚醒一次。
為了獲得毫秒級計時器粒度,您必須使用 Win32 多媒體計時器( C# 包裝器)。
不,它不會占用 CPU,它只會暫停您的線程至少那么長時間。 當您的線程暫停時,操作系統可以安排另一個不相關的線程來使用處理器。
Thread.Sleep(1) 如上所述不會占用 CPU。
以下是線程休眠(或多或少)時發生的情況:
最后一點,我不完全知道你在做什么,但看起來你正在嘗試扮演調度程序的角色,也就是說,睡眠為 CPU 提供時間做其他事情......
在少數情況下(確實很少)它可能沒問題,但大多數情況下你應該讓調度程序完成它的工作,它可能比你知道的更多,並且可以使工作比你做的更好。
應該避免小的睡眠時間,因為放棄其時間片的線程在重新發出信號時會獲得優先級提升,這可能導致高上下文切換。 在多線程/服務器應用程序中,這可能會導致抖動效果,因為線程正在爭奪 CPU 時間。 相反,依靠異步函數和同步對象,例如臨界區或互斥體/信號量。
這是一個舊線程,在我的很多搜索中都會出現,但 Win7 有一個新的調度程序,並且其行為似乎與上述不同。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
DateTime dtEnd = DateTime.Now.AddSeconds(1.0);
int i = 0;
while (DateTime.Now < dtEnd)
{
i++;
Thread.Sleep(1);
}
Console.WriteLine(i.ToString());
i = 0;
long lStart = DateTime.Now.Ticks;
while (i++ < 1000)
Thread.Sleep(1);
long lTmp = (DateTime.Now.Ticks - lStart) / 10000;
Console.WriteLine(lTmp.ToString());
Console.Read();
}
}
}
使用上面的代碼,我的第一個結果給出了 946。所以在使用 1ms 睡眠的 1 秒時間跨度內,我得到了 946 次喚醒。 這非常接近 1ms。
第二部分詢問以 1ms 為單位執行 1000 個睡眠事件需要多長時間。 我得到了 1034 毫秒。 同樣,將近1ms。
這是在使用 .Net 4.0 的 1.8ghz core2duo + Win7 上
編輯:記住,sleep(x) 並不意味着此時醒來,它意味着不早於這個時間喚醒我。 不能保證。 雖然,您可以增加線程的優先級,並且 Windows 應該在較低優先級的線程之前安排您的線程。
正如 Bob Nadler 提到的Thread.Sleep(1)
不保證 1ms 的睡眠時間。
下面是一個使用 Win32 多媒體計時器強制休眠 1 毫秒的示例。
[DllImport("winmm.dll")]
internal static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")]
internal static extern uint timeEndPeriod(uint period);
timeBeginPeriod(1);
while(true)
{
Thread.Sleep(1); // will sleep 1ms every time
}
timeEndPeriod(1);
在 C# GUI 應用程序中對此進行測試,我發現該應用程序使用了大約 50% 的 CPU。
有關此主題的更多討論,請參閱以下論壇主題:
不,它不會占用所有可用的 CPU,因為當另一個線程有工作要做時,操作系統的調度程序將關閉一個睡眠線程。
不,不會。 你幾乎看不到它。 在每秒不到 1000 次的某個地方,這個線程會醒來,在再次睡覺之前幾乎什么都不做。
編輯:
我不得不檢查。 在 Java 1.5 上運行,此測試
@Test
public void testSpeed() throws InterruptedException {
long currentTime = System.currentTimeMillis();
int i = 0;
while (i < 1000)
{
Thread.sleep(1);
i++;
}
System.out.println("Executed in " + (System.currentTimeMillis() - currentTime));
}
在我的 3ghz 機器上以每秒大約 500 個睡眠的速度運行。 我想 C# 應該大致相同。 我假設有人會為這個非常重要的現實世界基准報告 C# 數字。 順便說一下,沒有可觀察到的 CPU 使用率。
一個線程一次最多可以占用一個(邏輯)CPU。 並且 1 毫秒的睡眠不會占用大量資源。 不要出汗。
也看看這個: msdn論壇
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace Test
{
public static class Program
{
public static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 10; ++i)
{
sw.Reset();
sw.Start();
Thread.Sleep(50);
sw.Stop();
Console.WriteLine("(default) Slept for " + sw.ElapsedMilliseconds);
TimeBeginPeriod(1);
sw.Reset();
sw.Start();
Thread.Sleep(50);
sw.Stop();
TimeEndPeriod(1);
Console.WriteLine("(highres) Slept for " + sw.ElapsedMilliseconds + "\n");
}
}
[DllImport("winmm.dll", EntryPoint="timeBeginPeriod", SetLastError=true)]
private static extern uint TimeBeginPeriod(uint uMilliseconds);
[DllImport("winmm.dll", EntryPoint="timeEndPeriod", SetLastError=true)]
private static extern uint TimeEndPeriod(uint uMilliseconds);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.