2011-12-08 23 views
6

Tôi có một dll tiêu thụ bởi một dịch vụ. Công việc cơ bản của nó là chạy mỗi X phút và thực hiện một số kiểm tra hệ thống. Trong dll của tôi, tôi có một lớp cấp cao nhất tuyên bố một System.threading.timer và một Timercallback. Hàm khởi tạo cho lớp khởi tạo timerCallback với hàm chuỗi của tôi. Trong trình xử lý "Onstart" của tôi, tôi khởi tạo bộ hẹn giờ với timercallback và đặt thời gian tiếp theo để kích hoạt và khoảng thời gian. Trong trường hợp của tôi cứ 10 phút một lần. Thông thường trong các kiểm tra 10 phút này không có gì để làm nhưng dịch vụ buộc phải làm điều gì đó ít nhất một lần mỗi ngày tại một thời điểm nhất định.C# .NET 2 Threading.Timer - time drifting

Vấn đề của tôi: Tôi thấy rằng trong quá trình thử nghiệm, thời gian kiểm tra hàng ngày được thực hiện mỗi ngày là chậm drifitng ra khỏi thời gian bắt đầu mong muốn của 8,30. ví dụ. trong khoảng 20 ngày lẻ, thời gian của tôi đã trôi dạt từ 08.30 đến 08.31.35. Nó trôi dạt khoảng 4 - 6 giây mỗi ngày.

Câu hỏi của tôi: có ai biết lý do tại sao thời gian trôi dạt như thế này và làm cách nào tôi có thể gắn bó với thời gian quy định?

cảm ơn

+0

Tôi không chắc chắn dựa trên câu hỏi này nhưng có vẻ như bạn đang lên lịch hẹn giờ để làm điều gì đó trong 10 phút mà hành động đầu tiên của họ là lên lịch một tác vụ khác trong 10 phút. Không lên lịch một nhiệm vụ cứ 10 phút một lần. Bạn có thể đăng mã bộ đếm thời gian không? – Sign

+0

Tôi chỉ đặt hẹn giờ một lần, khi dịch vụ đầu tiên bắt đầu và tôi đặt nó để kích hoạt sau mỗi 10 phút. Cứ như cứ mỗi 10 phút "đánh dấu" từ đó dần dần trôi đi sau đó và sau đó. Khó khăn để thêm mã beecause tôi cant dường như đặt trả về vận chuyển trong hộp texc này! – Keith

+0

@Keith - Bạn không được giả sử có một cuộc thảo luận đầy đủ theo nhận xét. Nếu bạn có mã để đăng cập nhật câu hỏi của mình. –

Trả lời

6

Thời gian "trôi" vì bộ đếm thời gian đơn giản là không phải là tóm lược. Nếu bạn cần phải chạy mã của bạn càng sát càng tốt để một khoảng thời gian nhất định, bạn có thể làm một cái gì đó như thế này:

public void MyTimerCallback(object something) { 
    var now = DateTime.UtcNow; 
    var shouldProbablyHaveRun = new DateTime(
     now.Year, now.Month, now.Day, 
     now.Hour, now.Minute - (now.Minute % 10), 0); 
    var nextRun = shouldProbablyHaveRun.AddMinutes(10.0); 

    // Do stuff here! 

    var diff = nextRun - DateTime.UtcNow; 
    timer.Change(diff, new TimeSpan(-1)); 
} 

... giả sử bạn đang sử dụng một trường hợp System.Threading.Timer. Sửa đổi ví dụ nếu bạn đang sử dụng bất kỳ loại bộ hẹn giờ nào khác (có một số!).

+0

Điều này có vẻ tốt nhờ. Tôi đang sử dụng một system.threading.timer tôi sẽ thay đổi tốt hơn để Timers.Timer sau đó? – Keith

+1

Tôi đã cập nhật câu trả lời của mình để sử dụng 'System.Threading.Timer'. Bộ hẹn giờ khác nhau có lợi ích cho các tình huống khác nhau. Nếu bộ hẹn giờ của bạn đã hoạt động cho đến bây giờ, không có lý do gì để thay đổi. Chấp nhận trả lời của tôi là câu trả lời nếu nó phù hợp với bạn. :) –

+0

@Keith: 'System.Timers.Timer' thực sự sử dụng' System.Threading.Timer' đằng sau hậu trường. Vì vậy, nó không thực sự quan trọng, nhưng trước đây là một chút thuận tiện hơn để sử dụng. –

0

Tại sao không kiểm tra mỗi phút nếu hành động cần được thực hiện?

ví dụ:

if (DateTime.Now.Minute % 10) == 0 
+0

Nếu bộ hẹn giờ được bắt đầu lúc 6:01, cứ 10 phút một lần khi kiểm tra, 'DateTime.Now.Minute% 10' sẽ không là' 0' :) –

0

phải mất một số lượng hữu hạn của thời gian để làm các thao tác bạn đang làm trong xử lý phương pháp đếm thời gian của bạn, vì vậy nó có ý nghĩa rằng nó sẽ không xảy ra mỗi 10 phút đến thứ hai, đặc biệt là nếu bạn đang lên kế hoạch cho lần đánh thức tiếp theo sau khi thực hiện kiểm tra của bạn và như vậy. nếu bạn vẫn đang kiểm tra để trả lời là đã đến lúc thực hiện việc này, bạn nên làm cho bộ đếm thời gian của bạn kích hoạt thường xuyên hơn để thỏa mãn độ phân giải bạn cần và tin tưởng kiểm tra khi nào cần thực hiện điều gì đó để đảm bảo nó hoạt động. bạn có thể cần một số loại kiên trì để đảm bảo nó không thực hiện hai lần (nếu điều đó quan trọng) trong trường hợp có một shutdown/restart và trạng thái biết liệu nó đã chạy chưa có trong bộ nhớ hay chưa.

+0

Xin chào, cách tôi hiểu là sự kiện hẹn giờ sẽ được kích hoạt sau mỗi x phút khi Id thiết lập nó. công việc tôi đang làm trong chủ đề của tôi là tách biệt khỏi điều đó? vì vậy liệu Id có hoàn thành công việc của tôi hay không, sự kiện 10 phút tiếp theo sẽ đến. Để kết thúc tôi có một "bận rộn" biến tôi thiết lập và chỉ "làm việc" nếu không bận rộn. Nếu điều đó hợp lý? – Keith

+0

tùy thuộc vào loại bộ hẹn giờ bạn đang sử dụng và cách bạn thiết lập bộ hẹn giờ. Tuy nhiên, vấn đề là các bộ đếm thời gian không đủ chính xác để tính vào việc thực thi thứ hai trong một vài phút chỉ dựa trên việc thực hiện các sự kiện hẹn giờ. –

0

Đây là quan điểm của tôi:

while ((DateTime.Now - lastRunTime).TotalSeconds < 600) 
    CurrentThread.Sleep(1000); 

hoặc chỉ đăng ký một cửa sổ hẹn giờ và thực hiện để đáp ứng với sự kiện/callback

public static void Main() 
{ 
    System.Timers.Timer aTimer = new System.Timers.Timer(); 
    aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent); 
    // Set the Interval to 600 seconds. 
    aTimer.Interval=600000; 
    aTimer.Enabled=true; 

    Console.WriteLine("Press \'q\' to quit the sample."); 
    while(Console.Read()!='q'); 
} 

// Specify what you want to happen when the Elapsed event is raised. 
private static void OnTimedEvent(object source, ElapsedEventArgs e) 
{ 
    Console.WriteLine("10 minutes passed!"); 
} 
0

Bộ hẹn giờ không chính xác, chỉ gần đúng. Không sử dụng logic "chỉ cần thêm 10 phút". Mỗi khi bộ đếm thời gian của bạn kích hoạt, bạn cần phải kiểm tra thời gian nghiêng và điều chỉnh.

ví dụ: Nếu bạn nói "đánh thức tôi dậy trong 10 phút", và nó đánh thức bạn dậy trong 10 phút 1 giây, thì bộ đếm thời gian tiếp theo cần phải là 9 phút 59 giây, không phải 10 phút.

Ngoài ra, bạn muốn chỉ định bộ hẹn giờ tiếp theo ở cuối logic của mình.

ví dụ: nói rằng bạn muốn bắt đầu taskA mỗi 10 phút và mất 2 giây để chạy.Bộ hẹn giờ của bạn bắt đầu và 10 phút sau nó sẽ thức dậy để chạy taskA. Nó bắt đầu, kết thúc, bây giờ bạn thêm 10 phút. Nhưng phải mất 2 giây để chạy nhiệm vụ của bạn. Vì vậy, 10 phút kể từ khi mã của bạn chạy sẽ bị lệch 2 giây.

Những gì bạn cần làm là dự đoán lần sau bạn cần chạy và tìm sự khác biệt giữa bây giờ và sau đó và đặt bộ hẹn giờ cho sự khác biệt đó.

+0

Nhưng tôi không "thêm" 10 phút. Im thiết lập một bộ đếm thời gian một lần, yêu cầu nó kích hoạt sau mỗi 10 phút và sau đó chạy mã của tôi trong sự kiện "OnFired". Nếu bạn hiểu ý tôi. – Keith