Как изменить интервал времени в System.Threading.Timer из функции обратного вызова этого таймера? - PullRequest
8 голосов
/ 25 мая 2011

Как изменить интервал в System.Threading.Timer из функции обратного вызова этого таймера?Это правильно?

Делать так.Не случилось.

public class TestTimer
{
    private static Timer _timer = new Timer(TimerCallBack); 

    public void Run()
    {
        _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(1));
    }

    private static void TimerCallBack(object obj)
    {
        if(true)
            _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10));
    }

}

Ответы [ 2 ]

11 голосов
/ 25 мая 2011

Эта строка генерирует бесконечную рекурсию:

if(true)
    _timer.Change(TimeSpan.Zero, TimeSpan.FromMinutes(10));

Первый параметр заставляет TimerCallBack выполняться сразу. Таким образом, он выполняет его снова и снова на неопределенный срок.

Исправление будет

if(true)
    _timer.Change(TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
4 голосов
/ 25 мая 2011

Проблема в том, что ваш звонок на Change указывает, что следующий вызов должен произойти немедленно .Если вы собираетесь звонить Change каждый раз, вы можете просто использовать период Timeout.Infinite (который является просто константой -1), чтобы сказать, что следует избегатьповторяется вообще после следующего раза - но он все равно будет продолжать стрелять, потому что в следующий раз вы его сбросите.Например:

using System;
using System.Threading;

static class Program
{
    private static Timer timer = new Timer(TimerCallBack); 

    public static void Main()
    {
        timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
        Thread.Sleep(10000);

    }

    private static void TimerCallBack(object obj)
    {
        Console.WriteLine("{0}: Fired", DateTime.Now);
        timer.Change(TimeSpan.FromSeconds(3),
                     TimeSpan.FromMilliseconds(Timeout.Infinite));
    }
}

Кроме того, вы можете изменить его только один раз, а затем оставить его:

using System;
using System.Threading;

static class Program
{
    private static Timer timer = new Timer(TimerCallBack); 
    private static bool changed = false;

    public static void Main()
    {
        timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1));
        Thread.Sleep(10000);

    }

    private static void TimerCallBack(object obj)
    {
        Console.WriteLine("{0}: Fired", DateTime.Now);
        if (!changed)
        {
            changed = true;
            TimeSpan interval = TimeSpan.FromSeconds(3);
            timer.Change(interval, interval);
        }
    }
}

Обратите внимание, что ничто не использует начальный интервал (1 секунда в приведенных выше примерах).) в любом случае, потому что мы вызываем Change немедленно - если вы действительно хотите другое время перед первым вызовом, не используйте TimeSpan.Zero при первоначальном вызове Change.

...