【问题标题】:Await a thread wont work when dispatch inside of the thread在线程内部分派时等待线程不起作用
【发布时间】:2022-01-20 06:05:28
【问题描述】:

我正在一个新线程中运行一个任务,并希望等待它完成。

var a = "logic before the task starts";
await Task.Factory.StartNew(() => MyHugeFunction(_token), _token);
var b = "logic after the task is finished";

它运行良好,直到我开始在线程内部调度:

 await Application.Current.Dispatcher.BeginInvoke(new Action(async () =>
 {
    SomeLogic();
 }));

任务本身可以工作,但我正在运行的任务的等待不再工作。一旦我在线程中调度,var b 将被分配到主线程中。

我已经有了一些解决方法,但我只是想知道我是在做一些愚蠢的事情还是这是由其他情况引起的

我正在使用 C# 8.0 和 .Net Framework 4.7.2。

【问题讨论】:

  • BeginInvoke 在将 Action 传递到调度程序队列后立即返回。目前尚不清楚您要在这里做什么。也许使用 Invoke 而不是 BeginInvoke。
  • 从异常处理的角度来看,比起Dispatcher.BeginInvoke,更喜欢Dispatcher.InvokeAsync
  • @Clemens 谢谢!调用而不是 BeginInvoke 为我修复了它。
  • @Joe Dispatcher.InvokeAsync 会导致同样的问题。只是 Invoke 为我做了这件事。但是谢谢:)
  • Joe 的评论并不是为了解决您的问题,而只是告诉如果您想要进行异步 Dispatcher 调用,InvokeAsync 比 BeginInvoke 更适合。

标签: c# wpf multithreading async-await dispatch


【解决方案1】:

我正在一个新线程中运行一个任务,并希望等待它完成。

您想为此使用Task.Run 而不是StartNewStartNew 是一个危险的低级 API,几乎不应该使用,在少数情况下应该使用它,你应该始终 传递一个TaskScheduler

等待 Application.Current.Dispatcher.BeginInvoke(new Action(async () =>

我马上阻止你。首先,您使用async 显式创建Action 委托,这会导致async void 方法,应该避免这种情况。接下来,使用Dispatcher 做任何InvokeBeginInvoke 真的根本不应该做。

改为使用Progress<T> 类型。这会将您的逻辑保留在后台线程中,后台线程可以将对象作为更新传递给 UI 线程,UI 线程 决定如何在 UI 中显示这些进度更新。请注意那里很好的关注点分离,每当人们开始使用Dispatcher时,它往往会消失。

StartNewDispatcher 在 SO 答案和博客中都很常见,但无论如何它们都不是最佳解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2011-02-04
    • 1970-01-01
    相关资源
    最近更新 更多