当您通过 Start() 函数启动 Timer 对象时,它会创建一个新线程并等待直到经过的时间,然后当时间经过时,然后从计时器创建的线程调用订阅的函数或 lambda 或委托。因此,在您的示例中, timer_elapse 在完全不同的线程上运行。请参阅示例 WPF MainClass 中的以下示例:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
System.Threading.Thread.CurrentThread.Name = "UI THREAD";
System.Timers.Timer t = new System.Timers.Timer(500);
System.Threading.Thread td = new System.Threading.Thread(
(obj) =>
{
Console.WriteLine("Thread");
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
while (true)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine("From Lambda: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name);
}
}
);
td.Name = "K's Thread";
td.Start(null);
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("t_Elapsed: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name);
}
}
并注意调试控制台中的输出,Timer 函数的 Thread 名称与 UI Thread 名称不同。
因此,您不必担心挂起您的 UI 线程。但是,如果您尝试更改某些控件,则可能会引发异常(并非总是如此)。因此,要执行任何与 UI 相关的工作,最好在 UI 线程中执行。您可以将 Dispatcher 从Application.Current.Dispatcher
示例如下:
public partial class MainWindow : Window
{
delegate void TestDelegate();
public MainWindow()
{
InitializeComponent();
System.Threading.Thread.CurrentThread.Name = "UI THREAD";
System.Timers.Timer t = new System.Timers.Timer(500);
System.Threading.Thread td = new System.Threading.Thread(
(obj) =>
{
Console.WriteLine("Thread");
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
while (true)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine("From Lambda: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name);
}
}
);
td.Name = "K's Thread";
td.Start(null);
}
void DoInUIThread()
{
Console.WriteLine("DoInUIThread: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name);
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("t_Elapsed: Current Thread Name: " + System.Threading.Thread.CurrentThread.Name);
TestDelegate td = new TestDelegate(DoInUIThread);
Application.Current.Dispatcher.BeginInvoke(td );
}
}