Таймер для перезапуска функции по завершении - PullRequest
1 голос
/ 25 мая 2020

Я сейчас застрял над проблемой с таймером.

У меня есть функция, которая запускается таймером каждые x секунд. Теперь выполнение функции иногда может занимать больше времени в разных условиях. Поэтому я хочу, чтобы таймер перезапускался только тогда, когда он завершил свою функцию. Как мне этого добиться?

Ответы [ 2 ]

3 голосов
/ 25 мая 2020

Прямо перед выходом ваша функция могла вызвать событие. Событие будет перехвачено другой функцией, которая запустит таймер.

1 голос
/ 25 мая 2020

Я бы посоветовал избегать использования для этого класса Timer. Причиной этого как раз и являются проблемы, с которыми вы столкнулись сейчас. метод снова, даже если он уже выполняется. Вам необходимо организовать взаимодействие между методом и триггером таким образом, чтобы код был немного запутанным.

Однако давайте переосмыслим проблему.

Вызов метода в интервале Если вызов метода занимает больше времени, чем интервал, немедленно запускать снова

Лучшим способом было бы обойтись без триггера и напишите свои собственные, используя задачи.

Вот очень простой пример:

public static async Task CallPeriodicAsync(Func<CancellationToken, Task> func,
    int intervalMilliseconds, CancellationToken cancellationToken)
{
    while (true)
    {
        var delay = Task.Delay(intervalMilliseconds, cancellationToken);
        await func(cancellationToken);
        await delay;
    }
}

Вы должны начать это так:

CancellationToken cancellationToken = ...;
CallPeriodicAsync(async ct =>
{
    int timeToRun = 1000 + r.Next(14000);
    Console.WriteLine($"This time running for {timeToRun} ms");
    await Task.Delay(timeToRun, ct);
}, 10000, cancellationToken);

Пример вывода будет (я также имел некоторый Console.WriteLine в методе CallPeriod, чтобы сказать, будет ли он ждать или немедленно запускаться в этом запуске):

This time running for 12162 ms
trigger again immediately
This time running for 14706 ms
trigger again immediately
This time running for 12756 ms
trigger again immediately
This time running for 2187 ms
delay until next is 7813 ms
This time running for 5221 ms
delay until next is 4767 ms
This time running for 8866 ms

Обычно этот метод CallPeriod вызывает ваш метод и дает ему X миллисекунд для завершения. Если он завершится быстрее, он добавит задержку для остатка, если он завершится медленнее, он просто перезапустит цикл.

Это означает, что мой вопрос о «сохранении исходного интервала» по-прежнему актуален.

Например, сохранение исходного интервала приведет к такому типу запуска (---* - это просто временная шкала) каждые 4 секунды:

v               v               v               v               v
*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*
[...]           [..................][.......]   [...]           [....

, тогда как мое решение выше исказит цикл после задержки :

v               v               v                   v               v
*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*
[...]           [..................][.......]       [...]           [....
                                v                   ^
                                +-- because we got -+
                                 one second delayed
                                 here we're now one
                                 second late always
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...