У меня есть консоль C#, которую я сделал в службе Windows, которую я хотел бы выполнять надежно и постоянно.Несколько таймеров/обратных вызовов - лучший подход для предотвращения дублирования и для мониторинга их
- Я хочу предотвратить перекрытие того же таймера снова обжиг
- Я хочу, чтобы предотвратить различные таймеры пытаются использовать тот же ресурс сразу
- Я хочу, чтобы иметь возможность следить за таймеры и взаимодействовать с ними.
У него есть несколько аспектов. Каждый работает очень регулярно. Ранее я читал о TaskScheduler vs Windows Service, использующем подобные вещи, и выбрал этот подход, потому что что-то работает почти постоянно.
- TaskType1
- TaskType2
- TaskType3
- TaskType4
Я использую функции обратного вызова таймера, каждый со своим собственным, подобно этой упрощенной версии:
class Program
{
static PollingService _service;
static void Main()
{
_service = new PollingService();
TimerCallback tc1 = _service.TaskType1;
TimerCallback tc2 = _service.TaskType2;
TimerCallback tc3 = _service.TaskType3A;
TimerCallback tc4 = _service.TaskType3B;
Timer t1 = new Timer(tc1, null, 1000, 5000);
Timer t2 = new Timer(tc2, null, 2000, 8000);
Timer t3 = new Timer(tc3, null, 3000, 11000);
Timer t4 = new Timer(tc4, null, 4000, 13000);
Console.WriteLine("Press Q to quit");
while (Console.ReadKey(true).KeyChar != 'q')
{
}
}
}
class PollingService
{
public void TaskType1(object state)
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"TaskOne numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType2(object state)
{
for (int i = 10; i <= 100; i++)
{
Console.WriteLine($"TaskTwo numbering {i}");
Thread.Sleep(100);
}
}
public void TaskType3A(object state)
{
Increment(200000000);
}
public void TaskType3B(object state)
{
Increment(40000);
}
private void Increment(int startNumber)
{
for (int i = startNumber; i <= startNumber + 1000; i++)
{
Console.WriteLine($"Private {startNumber} numbering {i}");
Thread.Sleep(5);
}
}
}
Во-первых, я хочу, чтобы они не связывались друг с другом, когда они иногда длились долго.
Например. Если задание занимает 20 секунд для запуска, я хочу предотвратить дублирование таймера, пока предыдущий все еще может работать, то же самое для всех таймеров. Например. если t2 работает немного дольше обычного, то не запускайте другое. Я немного читал о if (Monitor.TryEnter(lockObject))
, это лучший способ справиться с этим требованием?
Во-вторых, если они оба обращаются к одному и тому же ресурсу (в моем случае - к контексту EF), так что t3 уже использует его, и t4 пытается это сделать. Есть ли способ попросить таймера подождать, пока другой не закончит?
Наконец-то есть способ, которым я могу контролировать эти таймеры/обратные вызовы? Я хотел бы предоставить пользовательский интерфейс, чтобы увидеть состояние этого, когда он работает как служба Windows. Мой эндшпиль заключается в том, чтобы предоставить пользовательский интерфейс, который пользователи могут видеть, если задача запущена, а если нет, то запускайте ее по требованию, если она не будет запущена на некоторое время. Но на одном дыхании не создавайте дубликат во время работы.
Я задался вопросом, следует ли мне задавать эти вопросы как отдельные вопросы, но они кажутся настолько переплетенными с решением друг друга.
Спасибо @Brandon, я работаю над этим. Как я могу добиться задержки, скажем, я хочу, чтобы Method1 работал только каждые 10 минут? Должен ли я держать поток открытым с помощью Thread.Sleep? –
Поток всегда будет работать, предполагая, что вы не вызываете отмену. Если мы говорим о ** A. ** выше (я написал их для удобства идентификации), первая строка, которую вы имели бы после циклов while, была бы условием 'if', определенным для этого цикла, который скажет вам независимо от того, действительно ли вам нужно что-то обрабатывать. Проверьте очередь/буфер, логическое поле, состояние какого-либо объекта или много чего. Что-то должно быть в состоянии сказать вам, должен ли этот поток выполнять какую-либо фактическую работу. – Brandon