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;
}
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
我实现了一个基本的 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;
}
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