新线程中的 DispatcherTimer
DispatcherTimer in a new thread
我正在开发 C# 应用程序。我需要 2 个线程;主要的一个,另一个是不断通过我的数据库查找信息。
我想将 Dispatcher Timer
用作:
dispatcherBd.Tick += (s,e) => CallPoll (s,e);
dispatcherBd.Interval = new TimeSpan(0,0,0,100);
dispatcherBd.Start();
如果我在我的主线程中执行此操作,则一切正常,但如果我在新线程中执行此操作。没用。
public Main(){
threadDB = new Thread(InitDispatcher);
threadDB.Start();
}
private void InitDispatcher(){
DispatcherTimer dispatcherBd.Tick += (s,e) => CallPoll (s,e);
dispatcherBd.Interval = new TimeSpan(0,0,0,100);
dispatcherBd.Start();
}
有什么问题?
如您在评论中所述,您将 dispatcherBd
声明为 local 变量 inside InitDispatcher()
:
private void InitDispatcher()
{
DispatcherTimer dispatcherBd = new DispatcherTimer();
// ...
因此 dispatcherBd
仅在 InitDispatcher
内的范围内,并且一旦离开该方法将可用于垃圾回收。
当它被垃圾收集并完成时,将不再引发计时器事件。
所以尝试将 dispatcherBd
改为 字段 :
private DispatcherTimer dispatcherBd;
private void InitDispatcher()
{
dispatcherBd = new DispatcherTimer();
// ...
但请注意 DispatcherTimer
在 UI 线程上调用其处理程序。因此,如果 CallPoll
花费大量时间,您的 UI 将被阻止。
所以你可能想从计时器的处理程序启动另一个线程:
dispatcherBd.Tick += (s, e) => { Task.Run(() => CallPoll(s, e)) };
或使用 System.Threading.Timer
而不是 DispatcherTimer
。那个在线程池线程上运行 Tick
事件。
在这两种情况下,当您想要在 UI 上显示结果时,您需要返回到 UI 线程。
除非绝对必要,否则请忘记手动穿线。使用 Task.Run
作为在另一个线程上安排您的(可能的,连续的)工作的一种方式。如果您需要从新创建的(非UI)线程更新您的 UI,请不要忘记 Dispatcher.Invoke
代理。
如果事情变得太复杂,请考虑 Reactive Extensions
。有开箱即用的定时器,还有很多很多。
我正在开发 C# 应用程序。我需要 2 个线程;主要的一个,另一个是不断通过我的数据库查找信息。
我想将 Dispatcher Timer
用作:
dispatcherBd.Tick += (s,e) => CallPoll (s,e);
dispatcherBd.Interval = new TimeSpan(0,0,0,100);
dispatcherBd.Start();
如果我在我的主线程中执行此操作,则一切正常,但如果我在新线程中执行此操作。没用。
public Main(){
threadDB = new Thread(InitDispatcher);
threadDB.Start();
}
private void InitDispatcher(){
DispatcherTimer dispatcherBd.Tick += (s,e) => CallPoll (s,e);
dispatcherBd.Interval = new TimeSpan(0,0,0,100);
dispatcherBd.Start();
}
有什么问题?
如您在评论中所述,您将 dispatcherBd
声明为 local 变量 inside InitDispatcher()
:
private void InitDispatcher()
{
DispatcherTimer dispatcherBd = new DispatcherTimer();
// ...
因此 dispatcherBd
仅在 InitDispatcher
内的范围内,并且一旦离开该方法将可用于垃圾回收。
当它被垃圾收集并完成时,将不再引发计时器事件。
所以尝试将 dispatcherBd
改为 字段 :
private DispatcherTimer dispatcherBd;
private void InitDispatcher()
{
dispatcherBd = new DispatcherTimer();
// ...
但请注意 DispatcherTimer
在 UI 线程上调用其处理程序。因此,如果 CallPoll
花费大量时间,您的 UI 将被阻止。
所以你可能想从计时器的处理程序启动另一个线程:
dispatcherBd.Tick += (s, e) => { Task.Run(() => CallPoll(s, e)) };
或使用 System.Threading.Timer
而不是 DispatcherTimer
。那个在线程池线程上运行 Tick
事件。
在这两种情况下,当您想要在 UI 上显示结果时,您需要返回到 UI 线程。
除非绝对必要,否则请忘记手动穿线。使用 Task.Run
作为在另一个线程上安排您的(可能的,连续的)工作的一种方式。如果您需要从新创建的(非UI)线程更新您的 UI,请不要忘记 Dispatcher.Invoke
代理。
如果事情变得太复杂,请考虑 Reactive Extensions
。有开箱即用的定时器,还有很多很多。