【问题标题】: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 的方法的返回值吗@ 没有像第一个例子那样定义对象?

【问题讨论】:

    标签: c# wpf multithreading user-interface invoke


    【解决方案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。那么你已经在后台线程中了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多