0

基于以下问题: General purpose FromEvent method

我如何知道事件将返回我的应用程序中的哪个线程?我可以以某种方式指定它将继续哪个线程?使用此功能的线程会发生什么情况?

当我使用 WPF(Dispatcher/Main/UI 线程)时,这些响应似乎很明显,但如果我正在使用线程 MTA、STA、Reactive、ThreadPool(Task/BackgroundWorker),我如何预测会发生什么?

使用 task.Wait() 有什么真正的好处(如果我不必担心锁定线程)?

4

3 回答 3

2

如果您awaitTask,则有一个“上下文”被捕获并用于恢复该async方法。这个“上下文”是当前的SynchronizationContext,除非它是null,在这种情况下它是当前的TaskScheduler(现在通常是线程池调度程序)。

如果你在做async编程,你应该使用await而不是Wait. Wait正如我在博客中解释的那样,可能会导致死锁

您可能还会发现我的async/await介绍很有帮助。

于 2013-01-23T18:43:53.363 回答
2

我如何知道事件将返回我的应用程序中的哪个线程?

你没有。你永远不会处理事件,除非特定事件的文档指定它将从 UI 线程、线程池线程等执行。

我可以以某种方式指定它将继续哪个线程?

如果要在 UI 线程中运行代码,则在事件处理程序中编组到 UI 线程。如果要在线程池线程中运行代码,则将新任务添加到处理程序内部的线程池中。如果不需要,这两项任务都会增加开销,因此通常最好查看事件的文档以了解需要哪些任务。

但是,在链接问题的情况下,整个想法是您不再处理事件和事件处理程序,而是处理Task. 因此,如果您向任务添加延续,问题是该延续将在哪里运行?这完全由您指定。您可以使用默认任务调度程序并让它在线程池中运行,您可以传递一个 UI SynchronizationContext 以在 UI 线程中运行,或者您可以让它在您继续运行的任务的任何地方运行。(这意味着您不知道哪个线程将运行它。)

如果您将任务与 一起使用await,那么它将自动将延续配置为在您开始该异步操作之前所在的同步上下文中运行,这可能是也可能不是 UI 线程(但很可能是)。如果您特别希望那样,请使用.ConfigureAwait(false);.

使用 task.Wait() 有什么真正的好处(如果我不必担心锁定线程)?

使用基于异步任务的方法的原因是您没有阻塞线程,尤其是线程池线程(因为您明确表示您没有阻塞 UI,这更糟糕)。让一个线程无所事事是一个问题,在某些环境中比其他环境更严重(例如用于高度活跃站点的 ASP)。通过不进行阻塞等待,您不会消耗这些资源。

于 2013-01-23T18:46:12.340 回答
1

使用您链接到的技术无法预测它运行的线程。可能是引发事件的线程,但这不能保证(不,真的!不是。这是一个常见的误解)。

因此,您需要强制切换到要运行的任何线程。例如用于Task.Run切换到线程池或用于TaskScheduler.FromCurrentSynchronizationContext在 UI 上运行。

如果您await的任务保证在await. 这可能就是你想要的。

于 2013-01-23T18:44:20.057 回答