Làm cách nào để chương trình C # của tôi ngủ trong 50 mili giây?
Đây có vẻ là một câu hỏi dễ, nhưng tôi đang có một khoảnh khắc suy não tạm thời!
Làm cách nào để chương trình C # của tôi ngủ trong 50 mili giây?
Đây có vẻ là một câu hỏi dễ, nhưng tôi đang có một khoảnh khắc suy não tạm thời!
Câu trả lời:
System.Threading.Thread.Sleep(50);
Tuy nhiên, hãy nhớ rằng việc thực hiện điều này trong luồng GUI chính sẽ chặn GUI của bạn cập nhật (nó sẽ cảm thấy "chậm chạp")
Chỉ cần loại bỏ ;
để làm cho nó hoạt động cho VB.net là tốt.
Về cơ bản có 3 sự lựa chọn để chờ đợi (gần như) bất kỳ ngôn ngữ lập trình nào:
cho 1. - Chờ đợi lỏng lẻo trong C #:
Thread.Sleep(numberOfMilliseconds);
Tuy nhiên, bộ lập lịch xử lý luồng của windows gây ra Sleep()
khoảng 15ms (vì vậy Ngủ có thể dễ dàng chờ trong 20ms, ngay cả khi được lên lịch chỉ chờ trong 1ms).
cho 2. - Chờ đợi chặt chẽ trong C # là:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do possible
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
}
Chúng ta cũng có thể sử dụng DateTime.Now
hoặc các phương tiện đo thời gian khác, nhưng Stopwatch
nhanh hơn nhiều (và điều này thực sự sẽ trở nên hữu hình trong vòng lặp chặt chẽ).
cho 3. - Kết hợp:
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
}
Mã này thường xuyên chặn luồng trong 1ms (hoặc hơn một chút, tùy thuộc vào lập lịch xử lý luồng của hệ điều hành), vì vậy bộ xử lý không bận trong thời gian chặn và mã không tiêu thụ 100% năng lượng của bộ xử lý. Việc xử lý khác vẫn có thể được thực hiện ở giữa chặn (chẳng hạn như: cập nhật giao diện người dùng, xử lý các sự kiện hoặc thực hiện công cụ tương tác / giao tiếp).
Bạn không thể chỉ định thời gian ngủ chính xác trong Windows. Bạn cần một hệ điều hành thời gian thực cho điều đó. Điều tốt nhất bạn có thể làm là chỉ định thời gian ngủ tối thiểu . Sau đó, đến lịch trình để đánh thức chủ đề của bạn sau đó. Và không bao giờ gọi .Sleep()
trên chủ đề GUI.
Kể từ bây giờ bạn có tính năng async / await, cách tốt nhất để ngủ trong 50ms là sử dụng Task.Delay:
async void foo()
{
// something
await Task.Delay(50);
}
Hoặc nếu bạn đang nhắm mục tiêu .NET 4 (với Async CTP 3 cho VS2010 hoặc Microsoft.Bcl.Async), bạn phải sử dụng:
async void foo()
{
// something
await TaskEx.Delay(50);
}
Bằng cách này, bạn sẽ không chặn luồng UI.
FlushAsync
phiên bản.
async
khai báo là gọiTask.Delay(50).Wait();
Sử dụng mã này
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
Các luồng sẽ không được lên lịch để thực thi bởi hệ điều hành trong khoảng thời gian được chỉ định. Phương pháp này thay đổi trạng thái của luồng để bao gồm WaitS ngủJoin.
Phương pháp này không thực hiện bơm COM và SendMessage tiêu chuẩn. Nếu bạn cần ngủ trên một luồng có STAThreadAttribution, nhưng bạn muốn thực hiện bơm COM và SendMessage tiêu chuẩn, hãy cân nhắc sử dụng một trong những tình trạng quá tải của phương thức Tham gia chỉ định khoảng thời gian chờ.
Thread.Join
Để dễ đọc:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
Tốt nhất của cả hai thế giới:
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);
}