Могу ли я использовать Threading.Timer в обратном вызове? - PullRequest
6 голосов
/ 08 марта 2011

Я использую Threading.Timer, например:

new Timer(new TimerCallback(y=>
{
    try
    {
        Save(Read(DateTime.Now));
        // here i want to dispose this timer
    }
    catch
    {                          
    }
}),null,100000,10000);

Как я могу использовать этот таймер внутри обратного вызоваили обходной путь?Обновление: позвольте мне объяснить ситуацию.Я хочу попробовать вызвать метод «Сохранить», пока он выдает исключение.Если это работает, мне нужно остановить таймер.

Ответы [ 5 ]

15 голосов
/ 08 марта 2011

Попробуйте:

Timer timer = null;
timer = new Timer(new TimerCallback(y =>
{    
    try    
    {
        Save(Read(DateTime.Now));        
        // here i want to dispose this timer
        timer.Dispose();    
    }    
    catch    
    {    
    }
}));
timer.Change(10000, 10000);

РЕДАКТИРОВАТЬ:

Я немного изменил приведенный выше код в соответствии с предложением Чу.Обратите внимание, что если TimerCallback вызывается одновременно различными событиями таймера, Timer.Dispose может закончиться вызовом несколько раз.К счастью, Timer не волнует, удаляется ли он несколько раз.

2 голосов
/ 16 октября 2014

Вот лучший способ сделать это. Когда вы используете конструктор только с одним параметром (TimerCallback), состояние, переданное обратному вызову, будет сам таймер.

Timer timer = new Timer(o =>
{
     ((Timer)o).Dispose();
     //Your code here     
});

//Start the timer
timer.Change(100000,10000);

Вот пример из документации MSDN:

public void StartTimer(int dueTime)
{
    Timer t = new Timer(new TimerCallback(TimerProc));
    t.Change(dueTime, 0);
}

private void TimerProc(object state)
{
    // The state object is the Timer object.
    Timer t = (Timer) state;
    t.Dispose();
    Console.WriteLine("The timer callback executes.");
}

http://msdn.microsoft.com/en-us/library/ms149618(v=vs.110).aspx

1 голос
/ 08 марта 2011

Вам нужно сохранить ссылку на таймер в переменной -

public class MyClass
{
    private Timer _timer;

    public void StartTimer()
    {
        _timer =  new Timer(new TimerCallback(y=>{
                            try
                            {
                                Save(Read(DateTime.Now));
                                _timer.Dispose();
                            }
                            catch { 

                            }
                        }),null,100000,10000);
    }



}

Примечание. Это непроверенный код. Пожалуйста, проверьте, работает ли это, и обновите.

0 голосов
/ 22 декабря 2015

Будьте осторожны, если вы используете многопоточность или многозадачность! если это так, то здесь вы - код и решение для экстензора метода CancelAfter (.net 4.0):

       private static object syncObj = new object();

       public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null)
    {
        if (timeoutMilliseconds == 0) return; // No timeout

        if (source == null)
        {
            throw new NullReferenceException();
        }
        if (timeoutMilliseconds < -1)
        {
            throw new ArgumentOutOfRangeException("timeout");
        }
        Timer timer = new Timer(delegate(object self)
        {
            lock (syncObj)
            {
                try
                {
                    if (null != code)
                        code.Invoke();
                    source.Cancel();

                    ((IDisposable)self).Dispose();
                }
                catch (ObjectDisposedException)
                {
                }                   
            }
        });
        timer.Change(timeoutMilliseconds, -1);
    }
}

С уважением, Хуанлу, ЭльГерре

0 голосов
/ 08 марта 2011

Вам нужно будет где-то сохранить ссылку на таймер и передать ее в качестве состояния самому объекту таймера. Попробуйте создать класс примерно так:

public class TimerContainer
{
  public Timer Timer { get; set; }
}

Затем используйте его в вашем методе так:

Action<object> tcb = state =>
{
  var container = (TimerConatiner)state;
  try
  {
    Save(Read(DateTime.Now));
    container.Timer.Dispose();
  }
  catch
  {
    // whatever...
  }
};

var container = new TimerContainer();
container.Timer = new Timer(tcb, container, 100000, 10000);
...