有一段第三方API代码SomeWork()
需要每隔3秒运行一次以监控某些物理设备。我想使用System.Timers.Timer并且它的Elapse事件是异步的,但是它每隔3秒就滞后于我的GUI操作。我尝试使用Dispatcher.BeginInvoke进行SomeWork()
但我仍然在GUI上遇到相同的延迟,即使SomeWork()
实际上没有更新任何GUI,也不应该占用GUI线程。
private void StartTimerAtStartup()
{
System.Timers.Timer connTimer = new System.Timers.Timer();
connTimer.Elapsed += new ElapsedEventHandler(MyTimer_Elapsed);
connTimer.Interval = 3000;
connTimer.Enabled = true;
}
private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.BeginInvoke(DispatcherPriority.Send, (ElapsedEventHandler)MyTimer_Elapsed, sender, e);
return;
}
// Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(
// () => SomeWork())
// );
SomeWork();
}
[EDIT1]
如果我删除所有Dispatcher并直接调用SomeWork(),那么我得到一个异常,我无法访问此线程。
[EDIT2]
SomeWork()是第三方API,用于侦听物理设备和接收数据包,但不接触GUI。我尝试了各种方法来执行Dispatcher.BeginInvoke,我遇到以下情况,我无法理解。为什么使用lamda会滞后GUI但是做一个委托并不会落后于GUI?
// This lags the GUI
Dispatcher.BeginInvoke(new Action( () => SomeWork() ));
// This does not lag the GUI. Application runs smooth,
// but I do not understand why
Dispatcher.BeginInvoke((Action)delegate () { SomeWork(); });
答案 0 :(得分:2)
您调用GUI线程的Dispatcher。因此,BeginInvoke调用异步工作到UI线程,并使您的UI滞后。
您的计时器在不同于UI线程的情况下触发Elapsed
事件。所以你只需在事件处理程序中调用你的方法。
但是,如果您需要每3秒钟严格调用一次API,而不是考虑执行SomeWork所需的时间或在分离的线程中完成工作。然后你可以使用任务来实现这一目标。
Task.Factory.StartNew(SomeWork);
但在这种情况下,你将不得不处理可能的竞争条件并同步你的工作。