向主线程调用方法的结果
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。那么你已经在后台线程中了。以上是关于向主线程调用方法的结果的主要内容,如果未能解决你的问题,请参考以下文章