в моем коде Мне нужно иметь таймер с длительным запуском, чтобы запускать какую-то рутину каждую первую секунду каждой минуты. Я попытался использовать System.Timers.Timer, но это не очень полезно из-за дрейфа таймера. Так что я реализовал таймер с реактивными расширений, тикает каждые 200 мс и поставить определенную логику в начале подпрограммы:C# наблюдаемый интервал пропускает тики
IObservable<Timestamped<long>> observable = Observable.Interval(TimeSpan.FromMilliseconds(200), Scheduler.NewThread).Timestamp();
IDisposable subscription = observable.Subscribe(x => calculator.Calculate(x.Timestamp));
Затем в методе Calculate:
public void Calculate(DateTimeOffset timeElapsed)
{
if (timeElapsed.Second != 1)
{
Log.Trace("Skip calc: second != 1. {0}", timeElapsed);
return;
}
if ((timeElapsed.LocalDateTime - lastRun).TotalSeconds < 59)
{
Log.Trace("Skip calc: interval < 60sec.");
return;
}
lastRun = timeElapsed.LocalDateTime;
var longRunningTask = new Task(() => CalcRoutine(timeElapsed), token);
longRunningTask.Start();
//etc..
}
Проблема заключается в том, что иногда без каких-либо понятных причин этот таймер пропускает около 7 тиков. В данном конкретном случае 2 последние тики отсутствуют в 7:57:00 и 7:57:01 всех вторые отсутствуют:
2015-05-22 07:56:59.1550|Skip calc: second != 1. 22.5.2015 7:56:59 +02:00
2015-05-22 07:56:59.3578|Skip calc: second != 1. 22.5.2015 7:56:59 +02:00
2015-05-22 07:56:59.5606|Skip calc: second != 1. 22.5.2015 7:56:59 +02:00
2015-05-22 07:56:59.7634|Skip calc: second != 1. 22.5.2015 7:56:59 +02:00
2015-05-22 07:56:59.9662|Skip calc: second != 1. 22.5.2015 7:56:59 +02:00
2015-05-22 07:57:00.1534|Skip calc: second != 1. 22.5.2015 7:57:00 +02:00
2015-05-22 07:57:00.3562|Skip calc: second != 1. 22.5.2015 7:57:00 +02:00
2015-05-22 07:57:00.5590|Skip calc: second != 1. 22.5.2015 7:57:00 +02:00
2015-05-22 07:57:02.1502|Skip calc: second != 1. 22.5.2015 7:57:02 +02:00
2015-05-22 07:57:03.3671|Skip calc: second != 1. 22.5.2015 7:57:03 +02:00
Это поведение не является правильным. Это случается случайным образом от одного до трех раз в день. Загрузка процессора в эти моменты является нормальной без всплесков. Диски тоже в порядке. Я не могу повторить это на своем компьютере. Кроме того, есть еще один пример того же приложения, у которого меньше работы, и он отлично работает. Приложения запускаются каждый день в полночь.
Что может вызвать эту проблему?
UPD: Полный код
static void Main(string[] args)
{
var calculatorReact = new Calculator();
IObservable<Timestamped<long>> observable = Observable.Interval(TimeSpan.FromMilliseconds(200)).Timestamp();
IDisposable subscription = observable.Subscribe(x => calculatorReact.Calculate(x.Timestamp));
Console.ReadLine();
}
public class Calculator
{
DateTime lastRun = DateTime.Now.AddDays(-1);
public void Calculate(DateTimeOffset timeElapsed)
{
//start calcuation on the 1st second of every minute
if (timeElapsed.Second != 1)
{
Console.WriteLine("Skip calc: second != 1. {0}", timeElapsed);
return;
}
if ((timeElapsed.LocalDateTime - lastRun).TotalSeconds < 59)
{
Console.WriteLine("Skip calc: interval < 60sec.");
return;
}
lastRun = timeElapsed.LocalDateTime;
var tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
var longRunningTask = new Task(() => {
Console.WriteLine("Calulating..");
}, token);
longRunningTask.Start();
}
}
UPD2 Проблема заключалась в синхронизации времени на этом сервере. По некоторым внутренним причинам нам приходилось использовать наше специальное программное обеспечение, которое быстро меняет системные часы, когда оно находит разницу. Поэтому он может легко переключать время с 7:57:00 до 7:57:02.
Извините за то, что вы не торопитесь.
Сигнатура для вашего '.Subscribe (...)' call не соответствует сигнатуре метода 'Calculate'. Можете ли вы предоставить код [минимальный, полный и проверенный] (http://stackoverflow.com/help/mcve), пожалуйста? – Enigmativity
Извините. Это должно быть 'IDisposable subscription = observable.Subscribe (x => calculator.Calculate (x.Timestamp));' –
Ваш код по-прежнему не завершен. Я пытаюсь запустить его в LINQPad, но слишком много отсутствующих элементов. Можете ли вы опубликовать код, который будет запускаться и давать результаты? – Enigmativity