Timer.Elapsed 和 BeginInvoke 仍然落后于 GUI

Timer.Elapsed and BeginInvoke still lag GUI

有一段第 3 方 API 代码,SomeWork(),需要每 3 秒 运行 来监控一些物理设备。我想使用 using 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() 是第 3 方 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(); });

你调用了GUI线程的Dispatcher。因此,BeginInvoke 将异步工作调用到 UI 线程,并且您的 UI 滞后。 您的计时器在与 UI 不同的线程中触发 Elapsed 事件。所以你可以简单地在事件处理程序中调用你的方法。

但是,如果您需要严格每 3 秒调用一次 API,那么您需要考虑执行 SomeWork 所需的时间或在单独的线程中完成该工作。然后你可以使用任务来实现它。

 Task.Factory.StartNew(SomeWork);

但在这种情况下,您将不得不处理可能的竞争条件并同步您的工作。