没有调用Timer方法

时间:2015-05-12 13:51:41

标签: c# .net timer

我已经设置了一个计时器:

System.Timers.Timer timer = new System.Timers.Timer (1000);
timer.Enabled = true;
timer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => {
            timer.Enabled = false;
            ui.CldOnPhoneNumberSent(); // <- this method is not fired
        };

不调用第二种方法。 如果我按以下方式切换方法:

timer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => {
    ui.CldOnPhoneNumberSent(); 
    timer.Enabled = false; // <- this method is not called and the timer repeats
}

出了什么问题?

修改 当从计时器调用该方法时,它不会被完全调用!:

timer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => {
                ((Timer)sender).Enabled = false;
                ui.method1();
};

void method1()
{
   do something; //<-- called
   do Something; //<-- not called 
}

2 个答案:

答案 0 :(得分:1)

匿名方法中的变量闭包可能存在问题 - 尝试使用sender值而不是引用timer

timer.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => {
        ((Timer)sender).Enabled = false;
        ui.CldOnPhoneNumberSent(); // <- this method is not fired
    };

答案 1 :(得分:0)

正如在评论中所说,最可能的原因是你的CldOnPhoneNumberSent()会引发一些阻止进一步执行的异常。

你应该重写如下:

var timer = new System.Timers.Timer (1000);
timer.Elapsed += (sender, args) =>
{
    ((Timer)sender).Enabled = false;
    try
    {
        ui.CldOnPhoneNumberSent();
    }
    catch (Exception e)
    {
        // log exception
        // do something with it, eventually rethrow it
    }
};
timer.Enabled = true;

请注意,如果您在WPF应用程序中并且想要访问在UI线程中创建的对象,则可能需要调度该调用:

Action callback = ui.CldOnPhoneNumberSent;
var app = Application.Current;
if (app == null)
{
    // This prevents unexpected exceptions being thrown during shutdown (or domain unloading).
    return;
}
if (app.CheckAccess())
{
    // Already on the correct thread, just execute the action
    callback();
}
else
{
    // Invoke through the dispatcher
    app.Dispatcher.Invoke(callback);
}

最后请注意,如果您使用.Net 4.5(使用C#5),您可以考虑使用async/await pattern而不是System.Timers.Timer,它更易于使用且更具可读性:

private async Task YourMethod()
{
    await Task.Delay(1000)
        .ConfigureAwait(continueOnCapturedContext: true); // this makes sure continuation is on the same thread (in your case it should be the UI thread)
    try
    {
        ui.CldOnPhoneNumberSent();
    }
    catch (Exception e)
    {
        // log exception
        // do something with it, eventually rethrow it
    }
}