如何在 dispatcher.begininvoke 上正确调用回调?

how to properly call callback on dispatcher.begininvoke?

我假设我可以直接调用

var dispatcherOp = Application.Current.Dispatcher.BeginInvoke(Action());
dispatcherOp.Completed += dispatcherOp_Completed;

但后来我有点担心。如果 begininvoke 是异步的,那么是什么阻止了调度程序在我获得返回的调度程序操作并附加到已完成的事件之前完成操作。

我假设这一定是不可能的,但如果是这样,我想知道为什么。

你是对的;这不安全。你应该简单地 await 操作。

答案是:没有。

存在三种可能的方法:

1.) 您可以决定等待操作执行并不重要。如果是,那么您选择了 fire and forget 策略。

2.) 你可以决定你想要一个同步请求,所以你等待,就像 SLaks 建议的那样。

3.) 您可以让请求保持异步,但使用 callback.

不幸的是,Dispatcher 没有 begininvoke 所需的回调函数。

我的程序不需要同步操作,但在 google 一两次搜索后我意识到我可以像这样锁定它

lock (this)
            {
                var dispatcherOp = Application.Current.Dispatcher.BeginInvoke(MyAction, DispatcherPriority.Normal);
                dispatcherOp.Completed += dispatcherOp_Completed;
            }



void dispatcherOp_Completed(object sender, EventArgs e)
        {
            lock (this)
            {

            }

        }

然后再次锁定已完成函数中的同一个对象,以便调度程序在您完成附加处理程序之前无法完成。

没有理由在现代应用程序中使用 Dispatcher.BeginInvoke

如果您的代码为后台操作建模,请使用 async/await,并使用 IProgress<T> 进行任何进度更新。

如果您的代码对异步序列建模,则将 Rx(响应式扩展)与 ObserveOn 结合使用,以更新具有 UI 线程关联的对象。