2009-07-07 6 views
42

Tôi đang chạy một dịch vụ cửa sổ và sử dụng một vòng lặp và Thread.Sleep để lặp lại một nhiệm vụ, nó sẽ là tốt hơn để sử dụng một phương pháp hẹn giờ?C# Timer hoặc Thread.Sleep

Nếu có một ví dụ mã sẽ là tuyệt vời

Tôi hiện đang sử dụng mã này để lặp lại

int curMinute; 
int lastMinute = DateTime.Now.AddMinutes(-1).Minute; 

while (condition) 
{ 
    curMinute = DateTime.Now.Minute; 

    if (lastMinute < curMinute) { 
     // do your once-per-minute code here 
     lastMinute = curMinute; 
    } 

    Thread.Sleep(50000);  // sleeps for 50 seconds 

    if (error condition that would break you out of this) { 
     break;  // leaves looping structure 
    } 
} 

Trả lời

30
class Program 
{ 
    static void Main(string[] args) 
    { 
     Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000); 
     Console.Read(); 
     timer.Dispose(); 
    } 

    public static void TimeCallBack(object o) 
    { 
     curMinute = DateTime.Now.Minute; 
     if (lastMinute < curMinute) { 
     // do your once-per-minute code here 
     lastMinute = curMinute; 
    } 
} 

Mã này có thể trông giống như một cái gì đó như trên

+5

Lưu ý rằng bộ hẹn giờ có thể phải chịu thêm các gian hàng hệ thống hoặc tải cao mà giấc ngủ có thể không. Điều này cần được xem xét trong quá trình thực hiện của bất kỳ ai. –

11

Điều quan trọng là phải hiểu rằng mã của bạn sẽ ngủ trong 50 giây giữa kết thúc một vòng lặp, và bắt đầu tiếp theo ...

Bộ hẹn giờ sẽ gọi vòng lặp của bạn sau mỗi 50 giây, không chính xác như vậy.

Cả hai đều hợp lệ, nhưng bộ hẹn giờ có thể là những gì bạn đang tìm kiếm ở đây.

4

Có, sử dụng Bộ hẹn giờ sẽ giải phóng một Chủ đề hiện đang dành phần lớn thời gian ngủ của mình. Bộ hẹn giờ cũng sẽ kích hoạt chính xác hơn mỗi phút để bạn có thể không cần phải theo dõi lastMinute nữa.

42

Bộ hẹn giờ là ý tưởng hay hơn, IMO. Bằng cách đó, nếu dịch vụ của bạn được yêu cầu dừng lại, nó có thể phản hồi rất nhanh và không gọi lại cho trình xử lý đánh dấu hẹn giờ ... nếu bạn đang ngủ, người quản lý dịch vụ sẽ phải chờ 50 giây hoặc giết thread, không ai trong số đó là terribly tốt đẹp.

+16

Để tránh giết chết các chủ đề, bạn có thể sử dụng một ManualResetEvent.WaitOne (50000) chứ không phải hơn Thread.Sleep(). Sau đó, bạn có thể Set() núm điều khiển chờ đợi để báo hiệu chuỗi sẽ kết thúc vào lúc thuận tiện sớm nhất. Một bộ đếm thời gian có lẽ vẫn sẽ thích hợp hơn trong trường hợp này. – Thorarin

2

Không khá trả lời các câu hỏi, nhưng thay vì phải

if (error condition that would break you out of this) { 
     break;  // leaves looping structure 
    } 

Bạn có lẽ nên có

while(!error condition) 

Ngoài ra, tôi đi với một Timer.

0

Bạn có thể sử dụng một thẻ. Nhưng tôi nghĩ rằng Sleep() dễ dàng, rõ ràng và ngắn hơn để triển khai.

7

Ghi chú rằng gọi Sleep() sẽ đóng băng các dịch vụ, vì vậy nếu các dịch vụ được yêu cầu dừng lại, nó sẽ không phản ứng trong suốt thời gian của Cuộc gọi Sleep().

1

Tôi yêu cầu một chủ đề để kích hoạt mỗi phút một lần (see question here) và bây giờ tôi đã sử dụng một số DispatchTimer dựa trên các câu trả lời tôi nhận được.

Câu trả lời cung cấp một số tài liệu tham khảo mà bạn có thể thấy hữu ích.

+0

+1 trước tiên phải đề cập đến DispatchTimer – LamonteCristo

0

Tôi đồng ý, sử dụng bộ hẹn giờ là tùy chọn tốt nhất. Tôi đã thử một giải pháp tương tự như của bạn trong quá khứ và bắt đầu có vấn đề mà vòng lặp sẽ không hài lòng, và tôi sẽ phải chờ đợi cho một Thread.Sleep() trước khi nó sẽ cháy một lần nữa. Ngoài ra, nó đã gây ra tất cả các loại vấn đề với việc ngừng dịch vụ, tôi sẽ nhận được các lỗi liên tục về cách nó không được đáp ứng và phải được đóng lại.

@ Mã của Prashanth phải chính xác những gì bạn cần.

1

Tôi đã sử dụng cả hai tính giờ và Thread.Sleep (x), hoặc là, tùy thuộc vào tình huống.

Nếu tôi có một đoạn mã ngắn cần chạy lặp lại, tôi có thể sử dụng bộ hẹn giờ.

Nếu tôi có một đoạn mã có thể mất nhiều thời gian chạy hơn bộ hẹn giờ trễ (chẳng hạn như truy xuất tệp từ máy chủ từ xa qua FTP, nơi tôi không kiểm soát hoặc biết độ trễ mạng hoặc kích thước/số lượng tệp) , Tôi sẽ đợi một khoảng thời gian cố định giữa các chu kỳ.

Cả hai đều hợp lệ, nhưng như đã chỉ ra trước đó, chúng thực hiện những việc khác nhau. Bộ đếm thời gian chạy mã của bạn mỗi x mili giây, ngay cả khi phiên bản trước đó chưa hoàn thành. Thread.Sleep (x) chờ một khoảng thời gian sau khi hoàn thành mỗi lần lặp, do đó, tổng độ trễ trên mỗi vòng lặp sẽ luôn dài hơn (có thể không nhiều) so với thời gian ngủ.

+1

+1 để chỉ ra, rằng khi sử dụng Bộ hẹn giờ, mã _could_ sẽ chạy nhiều lần cùng một lúc. – flocki

+0

Nó có thể, trừ khi bạn sử dụng một semaphore. – Casey

-1

Tôi sẽ phải nói rằng một giấc ngủ là một triển khai tốt hơn với một máy trạng thái phía sau nó. Điều này sẽ vẫn giữ cho bạn kiểm soát các ứng dụng mọi lúc, nhưng cho phép bất kỳ phản ứng cần thiết tại bất kỳ thời gian cụ thể. Điều này cũng sẽ xử lý callbacks timer được ngắn hơn so với "thời gian thực hiện chế biến trong vòng lặp"

Ví dụ ..

<!-- language: c# --> 
public enum State 
{ 
    Idle = 0, 
    Processing = 1, 
    Stop = 100, 
} 
public void Run() 
{ 
    State state = State.Idle; // could be a member variable, so a service could stop this too 

    double intervalInSeconds = 60; 
    System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds); 
    while (state != State.Stop) 
    { 
     switch (state) 
     { 
      case State.Idle: 
       { 
        if (nextExecution > System.DateTime.Now) 
        { 
         state = State.Processing; 
        } 
       } 
       break; 
      case State.Processing: 
       { 
        // do your once-per-minute code here 

        // if you want it to stop, just set it state to stop. 
        // if this was a service, you could stop execution by setting state to stop, also 
        // only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways 

        state = State.Idle; 
        nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds); 
       } 
       break; 
      default: 
       break; 
     } 

     System.Threading.Thread.Sleep(1); 
    } 
} 
+1

Và những gì bạn cảm thấy lợi thế ngủ thêm cho biết thêm bằng cách sử dụng một bộ đếm thời gian. Một số người khác đã đưa ra những nhược điểm của giấc ngủ mà bạn đã không giải quyết. – Servy

+0

Góc của tôi là duy trì quyền kiểm soát trong ứng dụng mọi lúc, một giấc ngủ và/hoặc bộ hẹn giờ dài sẽ không cho phép bạn xử lý mọi thứ trong khoảng thời gian nhỏ hơn thời gian chờ đã chọn. – Cr4t3r

+2

Đó là một vấn đề với việc thực hiện 'Sleep' ngây thơ, mà bạn cải thiện. Nó thậm chí không phải là một vấn đề trong một giải pháp dựa trên 'Timer'; bạn không xác định khoảng thời gian chờ, bạn xác định khoảng thời gian để kích hoạt sự kiện, vì vậy không có doanh nghiệp nào trong việc xác định thời gian chờ đợi cần được thực hiện chút nào. – Servy