2013-01-23 250 views
0

基于以下问题: General purpose FromEvent method异步/等待+ FromEvent方法

我怎么知道该事件将返回哪个线程在我的应用程序? 我可以以某种方式指定它会继续哪个线程? 使用此功能的线程会发生什么情况?当我使用WPF(Dispatcher/Main/UI线程)时,这些响应看起来很明显,但如果我正在使用线程MTA,STA,Reactive,ThreadPool(Task/BackgroundWorker),我该如何预测会发生什么?发生?

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

回答

2

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

你不知道。除非特定事件的文档指定它将从UI线程,线程池线程等执行,否则你从来不会使用事件。

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

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

但是,在链接问题的情况下,整个想法是,你不再处理事件和事件处理程序,你正在处理一个Task。所以如果你为任务添加一个延续,问题是这个延续会在哪里运行?这完全是由你指定的。您可以使用默认的任务计划程序并让它在线程池中运行,您可以传递一个UI SynchronizationContext以在UI线程中运行,或者您可以让它在任何正在运行的任务中运行。 (这意味着你不知道将使用什么线程运行它。)

如果您使用的任务是await,那么它会自动配置延续,以在您开始执行异步操作前的同步上下文中运行,这可能是也可能不是UI线程(但可能是)。如果您专门请不要想要的,那么请使用.ConfigureAwait(false);

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

使用基于异步任务的方法的原因是您没有阻塞线程,特别是线程池线程(因为您明确表示不会阻塞UI,这会更糟糕)。有一个线程坐在什么都不做是一个问题,在一些环境比其他更多(如一个高度活跃的网站的ASP)。通过不做阻塞等待,你没有消耗这些资源。

+1

“,除非特定事件的文档指定它将从UI线程,线程池线程等执行。”即使这样*任务延续*可能会运行在不同的线程上。 – usr

+0

@usr在这种情况下,我特指事件而不是任务。我稍后会在答案中找到任务。 – Servy

2

如果你有await a Task,那么有一个“上下文”被捕获并用于恢复方法。这个“上下文”是当前的SynchronizationContext,除非它是null,在这种情况下,它是当前的TaskScheduler(这些日子通常是线程池调度器)。

如果你正在做async编程,你应该使用await而不是WaitWait can cause deadlocks, as I explain on my blog

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

1

使用您链接到您的技术无法预测它运行的线程。它可能是是提高事件的线索,但这并不是保证(不,实际上!它不是,这是一个常见的错误信念)。

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

如果您await您保证在await之前设置的同步上下文中恢复该任务。 这可能是你想要的。