向主线程调用方法的结果

Posted

技术标签:

【中文标题】向主线程调用方法的结果【英文标题】:Invoking a method's result to the main thread 【发布时间】:2018-04-15 21:36:21 【问题描述】:

我想知道以下几点:

我有一个名为 Container 的可观察集合和一个名为 Method 的方法。

在主线程上,我想将Method 的返回值添加到Container

以下代码在另一个线程上运行,因此我必须将Container.Add 调用到应用程序当前线程才能没有错误:

object obj = Method()
App.Current.Dispatcher.Invoke(() => 
    Container.Add((MyObject)obj)
);

我的问题是我是否会做以下事情

App.Current.Dispatcher.Invoke(() => 
    Container.Add((MyObject)Method())
);

该方法(这是一个长时间运行的方法)将在应用程序当前线程上运行,这不太正确,因为它会处理 UI,我可以只调用要添加到 @987654328 的方法的返回值吗@ 没有像第一个例子那样定义对象?

【问题讨论】:

【参考方案1】:

您可以使用this Invoke overload:

Dispatcher.Invoke(new Action<MyObject>(o => Container.Add(o)), (MyObject)Method());

但是,您可以摆脱后台线程并在 Task 中调用 Method。因此,您将避免调用 Dispatcher.Invoke:

Container.Add(await Task.Run(() => (MyObject)Method()));

【讨论】:

第二个选项不要求调用方法标记为async吗? @Grx70 当然,像往常一样。 那么使用第一个例子,Method会在同一个线程上执行但结果只会被调用到UI线程? “调用结果”是一个没有多大意义的术语。在后台线程上调用该方法,然后将结果(对象引用)作为 Invoke 的参数传递给 UI 线程。 不,这(第一个例子)不会创建线程。您已经在后台线程中。调用 Invoke 只会在 UI 线程上执行 Action。【参考方案2】:

除了@Clemens 的提议,您可以使用Task-based Asynchronous Pattern (TAP):

App.Current.Dispatcher.Invoke(async () =>

    Container.Add(await Task.Run(() => Method()));
);

请注意,这需要 .NET 4.5 或更高版本,或 .NET 4 以及 Microsoft.Bcl.Async NuGet 包。

【讨论】:

现在您不再需要调用 Dispatcher.Invoke,因为不会有任何后台线程。 @Clemens 如果此代码在 UI 线程以外的线程上执行(从问题来看),您会这样做。不过我同意 Method 将在另一个线程上执行,就简单地摆脱变量而言,这并不是最好的解决方案。 如果有UI线程以外的线程,则不需要在Task中调用Method。那么你已经在后台线程中了。

以上是关于向主线程调用方法的结果的主要内容,如果未能解决你的问题,请参考以下文章

在新线程中调用方法的简单方法

一旦第一组工作线程完成处理,我如何使用 AutoResetEventHandler 向主线程函数发出信号以再次启动线程

从异步块向主线程发送参数时遇到问题

wpf中 我新开一个线程添加控件到主窗体

获取 异步执行调用的结果

多线程