UWP 中 Dispatcher.RunAsync 和 ThreadPool.RunAsync 的区别

Difference between Dispatcher.RunAsync and ThreadPool.RunAsync in UWP

我实现了一个基本的 AutoSave 方法,每次用户在 UWP 中的 InkCanvas 上绘制笔画时都会执行该方法。

我遵循了此处的代码片段 https://docs.microsoft.com/en-us/windows/uwp/threading-async/submit-a-work-item-to-the-thread-pool 以及使用 Dispatcher.RunAsync 的另一种方法。我想出了 3 种方法,其中一种会抛出 Marshall 异常

方法一(抛出)(https://docs.microsoft.com/en-us/windows/uwp/threading-async/submit-a-work-item-to-the-thread-pool)

    private void AutoSave()
    {
        IAsyncAction asyncAction
            = ThreadPool.RunAsync(
                async (workItem) =>
                {  
                  await ExportInk.SaveInkToLocalFileAsync(inkCanvas);
                });
        autoSaveWorkItem = asyncAction;

    }

方法二(https://docs.microsoft.com/en-us/windows/uwp/threading-async/submit-a-work-item-to-the-thread-pool)

    private void AutoSave()
    {
        IAsyncAction asyncAction
            = ThreadPool.RunAsync(
                async (workItem) =>
                {
                    await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
                        CoreDispatcherPriority.Normal,
                        new DispatchedHandler(async () =>
                        {
                            await ExportInk.SaveInkToLocalFileAsync(inkCanvas);
                        }));
                });
        autoSaveWorkItem = asyncAction;
    }

方法三(https://social.msdn.microsoft.com/Forums/en-US/d425e995-6822-4059-898f-0b5ff9586dfe/uwpcthe-application-called-an-interface-that-was-marshalled-for-a-different-thread-?forum=wpdevelop)

    private async void AutoSave()
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
          await ExportInk.SaveInkToLocalFileAsync(inkCanvas);
        });
    }

问题1方法1是否因为我在操作一个UI元素(InkCanvas)而抛出?

问题 2方法 2 和方法 3 之间有什么区别,为什么方法 3 似乎是首选方法?

提前感谢您的任何推荐

1 - 是的。您的应用程序中的每个 Window 都有一个单独的主线程用于它的 UI,并且您只能在该线程上操作 UI 元素。这可以通过 Window 的 Dispatcher 访问,它从 Window 的 UI 线程的任何线程调度消息。

ThreadPool.RunAsync 在某个任意 ThreadPool 线程上为 运行 创建一个工作项,该线程可能通常不会成为您的 UI 线程。

因为您要访问 UI 对象的某些 UI 属性,您需要在 UI 线程上才能执行此操作。

2 - 对于方法 2,您毫无意义地跳转到线程池线程只是为了告诉它返回到 UI 线程来完成它的工作。这是不必要的,因为 none 的工作将在该线程上完成,因为 Dispatcher 无论如何都会将其全部从 UI 线程发送出去。 3 避免那样 - 尽管如果自动保存已经从 UI 线程调用,甚至不需要 Dispatcher 调用。

如果您在单个 window 应用程序中,您实际上在 2 和 3 上使用了相同的 Dispatcher,只是访问它的方式不同。如果您的代码不在 DependencyObject 的代码隐藏中,您通过 2 访问的方式就是您执行此操作的方式。

有关 Dispatcher 的说明,请参阅 https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.dependencyobject#remarks