ฉันจะทำให้โปรแกรม C # ของฉันเข้าสู่โหมดสลีปเป็นเวลา 50 มิลลิวินาทีได้อย่างไร
นี่อาจเป็นคำถามง่าย ๆ แต่ฉันมีช่วงเวลาที่สมองล้มเหลวชั่วคราว!
ฉันจะทำให้โปรแกรม C # ของฉันเข้าสู่โหมดสลีปเป็นเวลา 50 มิลลิวินาทีได้อย่างไร
นี่อาจเป็นคำถามง่าย ๆ แต่ฉันมีช่วงเวลาที่สมองล้มเหลวชั่วคราว!
คำตอบ:
System.Threading.Thread.Sleep(50);
โปรดจำไว้ว่าการทำเช่นนี้ในเธรด GUI หลักจะบล็อก GUI ของคุณไม่ให้อัปเดต (มันจะรู้สึก "เฉื่อยชา")
เพียงแค่ลบ;
เพื่อให้มันทำงานได้กับ VB.net เช่นกัน
โดยทั่วไปมี 3 ตัวเลือกสำหรับการรอ (เกือบ) ภาษาการเขียนโปรแกรมใด ๆ :
สำหรับ 1. - การรอหลวมใน C #:
Thread.Sleep(numberOfMilliseconds);
อย่างไรก็ตามตัวกำหนดเวลาการเธรดของ windows ทำให้Sleep()
การรับรู้ข้อความอยู่ที่ประมาณ 15ms (ดังนั้น Sleep สามารถรอ 20ms ได้อย่างง่ายดายแม้ว่าจะถูกกำหนดให้รอเพียง 1ms)
สำหรับ 2 - การรออย่างแน่นหนาใน C # คือ:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do possible
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
}
เรายังสามารถใช้DateTime.Now
หรือวิธีการอื่นในการวัดเวลา แต่Stopwatch
เร็วกว่ามาก (และนี่จะทำให้มองเห็นได้ในวงแคบ)
สำหรับ 3 - การรวมกัน:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do STILL POSSIBLE
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
Thread.Sleep(1); //so processor can rest for a while
}
รหัสนี้จะบล็อกเธรดเป็นระยะเวลา 1ms (หรือมากกว่านั้นขึ้นอยู่กับการจัดตารางเธรดของระบบปฏิบัติการ) ดังนั้นโปรเซสเซอร์ไม่ว่างสำหรับช่วงเวลาของการบล็อกและรหัสไม่ใช้พลังงาน 100% ของโปรเซสเซอร์ การประมวลผลอื่น ๆ ยังสามารถทำได้ในระหว่างการปิดกั้น (เช่นการอัปเดต UI การจัดการเหตุการณ์หรือการโต้ตอบ / การสื่อสาร)
คุณไม่สามารถระบุเวลาพักเครื่องที่แน่นอนใน Windows คุณต้องใช้ระบบปฏิบัติการแบบเรียลไทม์สำหรับสิ่งนั้น สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือระบุเวลาพักเครื่องขั้นต่ำ จากนั้นขึ้นอยู่กับตัวกำหนดตารางเวลาเพื่อปลุกเธรดของคุณหลังจากนั้น และไม่เคยโทรหา.Sleep()
หัวข้อ GUI
ตั้งแต่ตอนนี้คุณมีคุณสมบัติ async / await วิธีที่ดีที่สุดในการนอนหลับ 50ms คือการใช้งาน TaskDelay:
async void foo()
{
// something
await Task.Delay(50);
}
หรือหากคุณกำหนดเป้าหมายเป็น. NET 4 (ด้วย Async CTP 3 สำหรับ VS2010 หรือ Microsoft.Bcl.Async) คุณต้องใช้:
async void foo()
{
// something
await TaskEx.Delay(50);
}
วิธีนี้คุณจะไม่บล็อกเธรด UI
FlushAsync
รุ่น
async
ประกาศคือการโทรTask.Delay(50).Wait();
ใช้รหัสนี้
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
เธรดจะไม่ถูกกำหนดเวลาสำหรับการดำเนินการโดยระบบปฏิบัติการตามระยะเวลาที่ระบุ เมธอดนี้เปลี่ยนสถานะของเธรดเพื่อรวม WaitSleepJoin
วิธีนี้ไม่ได้ทำการปั๊มมาตรฐาน COM และ SendMessage หากคุณต้องการนอนบนเธรดที่มี STAThreadAttribute แต่คุณต้องการทำการปั๊มมาตรฐาน COM และ SendMessage ให้ลองใช้หนึ่งในโอเวอร์โหลดของวิธีการเข้าร่วมที่ระบุช่วงหมดเวลา
Thread.Join
สำหรับการอ่าน:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
เริ่มต้นด้วย. NET Framework 4.5 คุณสามารถใช้:
using System.Threading.Tasks;
Task.Delay(50).Wait(); // wait 50ms
ดีที่สุดของทั้งสองโลก:
using System.Runtime.InteropServices;
[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);
/**
* Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
*/
private void accurateSleep(int milliseconds)
{
//Increase timer resolution from 20 miliseconds to 1 milisecond
TimeBeginPeriod(1);
Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < milliseconds)
{
//So we don't burn cpu cycles
if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
{
Thread.Sleep(5);
}
else
{
Thread.Sleep(1);
}
}
stopwatch.Stop();
//Set it back to normal.
TimeEndPeriod(1);
}