上回話說我們觀察到在不同的機器上,Thread.Sleep(1)的結果不一定就是1ms,而可能是以15ms為單位。

經過鍥而不舍的搜查,後來有了驚奇的發現! 原來這個事實是可以改變的,多媒體程式庫中有個timeBeginPeriod的API,可以設定Thread.Sleep的時間解析度,例如以下的寫法:

private static void TestSleep()

{

    timeBeginPeriod(1);

    Thread.Sleep(1);

    timeEndPeriod(1);

}

[DllImport("winmm.dll")]

internal static extern uint timeBeginPeriod(uint period);

[DllImport("winmm.dll")]

internal static extern uint timeEndPeriod(uint period);

於是我在上次的TestThreadSleep程式中加上timeBeginPeriod, timeEndPeriod的邏輯,測試結果馬上大不相同,Thread.Sleep不再懶床,原則上會逼近所要求的等待時間。以DL360為例,

使用前:

Thread.Sleep(25) Test:
23.968 ms, 31.266 ms, 30.447 ms, 31.165 ms, 31.041 ms, Avg = 29.577 ms
Thread.Sleep(15) Test:
15.682 ms, 15.291 ms, 15.557 ms, 15.521 ms, 15.550 ms, Avg = 15.520 ms
Thread.Sleep(10) Test:
15.486 ms, 15.463 ms, 15.682 ms, 15.418 ms, 15.517 ms, Avg = 15.513 ms
Thread.Sleep(5) Test:
15.472 ms, 15.552 ms, 15.535 ms, 15.569 ms, 15.709 ms, Avg = 15.568 ms
Thread.Sleep(1) Test:
15.290 ms, 15.539 ms, 15.559 ms, 15.551 ms, 15.554 ms, Avg = 15.499 ms

使用後:

Thread.Sleep(25) Test:
5.680 ms, 25.015 ms, 25.268 ms, 25.319 ms, 25.117 ms, Avg = 21.280 ms
Thread.Sleep(15) Test:
15.637 ms, 15.420 ms, 15.548 ms, 15.556 ms, 15.560 ms, Avg = 15.544 ms
Thread.Sleep(10) Test:
10.755 ms, 10.576 ms, 10.626 ms, 10.674 ms, 10.536 ms, Avg = 10.633 ms
Thread.Sleep(5) Test:
5.591 ms, 5.684 ms, 5.789 ms, 5.786 ms, 5.798 ms, Avg = 5.730 ms
Thread.Sleep(1) Test:
1.761 ms, 1.783 ms, 1.866 ms, 1.902 ms, 1.735 ms, Avg = 1.810 ms

不過,使用timeBeginPeriod時要注意,原則上調動它會造成系統不必要的負擔,記得不用了馬上timeEndPeriod恢復原狀。


Comments

# by fanncy

謝謝您的分享,非常感謝。

Post a comment


20 - 17 =