Làm cách nào để chương trình C # của tôi ngủ trong 50 msec?


272

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!


1
Được gắn thẻ lại vào VB.NET khi câu trả lời cũng hoạt động ở đó.
DrFloyd5

Không có DrFloyd5 ,; không hoạt động trên VB.NET, phải không?
Zanoni

16
Nếu tôi ở trong nhóm VB.Net, tôi sẽ thêm; như một nhân vật bình luận cho phiên bản tiếp theo của ngôn ngữ ...
Joel Coehoorn

4
Tôi nghĩ rằng các lập trình viên VB đủ sáng để tìm ra sự tương đương ..
BlueRaja - Danny Pflughoeft

tốt, chỉ để đảm bảo, bây giờ họ không phải làm thế.
PsychoData

Câu trả lời:


330
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.


Sau khi gọi chế độ ngủ trong một phương thức, chương trình có tiếp tục thực thi trong nền không (không tạo chủ đề mới)? Ngoài ra, nếu tôi gọi giấc ngủ trong một chủ đề mới, chủ đề chính sẽ tiếp tục công việc của nó?
Jay Nirgudkar

@JayNirgudkar chuỗi gọi Ngủ sẽ bị dừng. Các chủ đề khác không bị ảnh hưởng.
Isak Savo

Điều này không được đảm bảo là chính xác.
Akumaburn

150

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:

  1. Chờ đợi
    • Thực hiện các khối luồng trong thời gian nhất định (= không tiêu thụ năng lượng xử lý)
    • Không thể xử lý trên luồng bị chặn / chờ
    • Không chính xác lắm
  2. Chờ đợi chặt chẽ (còn gọi là vòng lặp chặt chẽ)
    • bộ xử lý RẤT bận rộn cho toàn bộ khoảng thời gian chờ đợi (trên thực tế, nó thường tiêu tốn 100% thời gian xử lý của một lõi)
    • Một số hành động có thể được thực hiện trong khi chờ đợi
    • Rất chính xác
  3. Kết hợp 2 trước
    • Nó thường kết hợp hiệu quả xử lý của 1. và sự chính xác + khả năng làm việc gì đó bằng 2.

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.Nowhoặc các phương tiện đo thời gian khác, nhưng Stopwatchnhanh 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).


1
Đồng hồ bấm giờ cũng có thể được quan tâm
JonnyRaa

55

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.


44

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.


bạn có thể answer.flush trong thời gian trễ này không, nếu nó ở trong một vòng lặp?
Teoman shipahi

Không, bạn không thể. Tôi tin rằng có một FlushAsyncphiên bản.
Toni Petrina

6
Một cách khác không yêu cầu asynckhai báo là gọiTask.Delay(50).Wait();
stuartd


14
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


0

Bắt đầu với .NET Framework 4.5, bạn có thể sử dụng:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

-1

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);
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.