2015-05-12 4 views
1

Я установки таймера:методы Таймер не называется

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 
} 

, что случилось?

Edit: Когда метод вызываются из таймера, это не называется полностью !:

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

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

Попробуйте использовать отладчик, установите контрольные точки и выполните свой код. –

+1

Может ли 'CldOnPhoneNumberSent' выбрасывать исключение? Запустили ли вы его в отладчике? –

+0

В частности, идентификатор 'ui' предполагает, что вы каким-то образом взаимодействуете с пользовательским интерфейсом, предположительно в приложении Winforms/WPF? В этом случае он всегда будет терпеть неудачу, поскольку вы не можете получить доступ к этим объектам из потоков, отличных от тех, на которых они были созданы. Вы действительно не хотите использовать 'System.Windows.Forms.Timer' вместо этого? – Luaan

ответ

1

Это может быть проблемой с переменным закрытием в анонимном методе - попробуйте использовать значение sender вместо реферирования timer:

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

Даже если при вызове второго метода (после некоторой конфигурации) внутренние методы не называются конкурсно! Я обновил свой вопрос. – Alterecho

0

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

Вы должны переписать следующим образом:

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 и хотите получить доступ к объекту, созданному в потоке пользовательского интерфейса, возможно, потребуется направить вызов:

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 
    } 
} 
Смежные вопросы