我可以在回调中处理Threading.Timer吗?

时间:2011-03-08 10:01:24

标签: .net callback timer dispose

我正在使用Threading.Timer,例如:

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

如何在回调中处理此计时器。或解决方法? 更新:让我解释一下情况。我想尝试调用方法“保存”,同时抛出异常。如果有效,我需要停止计时器。

5 个答案:

答案 0 :(得分:14)

试试这个:

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);

修改

我根据Chuu的建议稍微修改了上面的代码。请注意,如果通过不同的计时器事件同时调用TimerCallback,Timer.Dispose可能最终被调用多次。幸运的是,Timer并不关心它是否被多次处理。

答案 1 :(得分:2)

这是一种更好的方法。当您使用只有一个参数(TimerCallback)的构造函数时,传递给回调的状态将是计时器本身。

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

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

以下是msdn docs的一个例子:

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

答案 2 :(得分:1)

您需要将计时器的引用保留在变量中 -

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);
    }



}

注意:这是未经测试的代码。请检查它是否有效并更新。

答案 3 :(得分:0)

您必须在某处存储对计时器的引用,并将其作为状态传递给计时器对象本身。尝试创建类似这样的类:

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);

答案 4 :(得分:0)

如果您使用多线程或多任务处理,请小心!如果是这样,这里你是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);
    }
}

此致 Juanlu,ElGuerre