RunAsync - 如何等待 UI 线程上的工作完成? [英] RunAsync - How do I await the completion of work on the UI thread?

查看:24
本文介绍了RunAsync - 如何等待 UI 线程上的工作完成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当等待 Dispatcher.RunAsync 时,继续发生在工作被安排时,而不是在工作完成时发生.我如何等待工作完成?

When awaiting Dispatcher.RunAsync the continuation occurs when the work is scheduled, not when the work has completed. How can I await the work completing?

编辑

我最初的问题假设过早的延续是由 API 的设计引起的,所以这是真正的问题.

My original question assumed the premature continuation was caused by the design of the API, so here's the real question.

当使用异步委托等待 Dispatcher.RunAsync 时,在委托的代码中使用 await,当遇到 await 时会发生继续,不是在工作完成时.我如何等待工作完成?

When awaiting Dispatcher.RunAsync using an asynchronous delegate, using await within the delegate's code, the continuation occurs when the await is encountered, not when the work has completed. How can I await the work completing?

编辑 2

您可能需要分派已经在 UI 线程上的工作的一个原因是解决微妙的时间和布局问题.可视化树中元素的大小和位置值不断变化是很常见的,并且为 UI 的后续迭代安排工作会有所帮助.

One reason you may need to dispatch work that's already on the UI thread is to workaround subtle timing and layout issues. It's quite common for values of sizes and positions of elements in the visual tree to be in flux and scheduling work for a later iteration of the UI can help.

推荐答案

我在 Microsoft github 存储库:如何等待后台线程发送的 UI 任务.

CoreDispatcher定义这个扩展方法:

using System;
using System.Threading.Tasks;
using Windows.UI.Core;

public static class DispatcherTaskExtensions
{
    public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher, 
        Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
    {
        var taskCompletionSource = new TaskCompletionSource<T>();
        await dispatcher.RunAsync(priority, async () =>
        {
            try
            {
                taskCompletionSource.SetResult(await func());
            }
            catch (Exception ex)
            {
                taskCompletionSource.SetException(ex);
            }
        });
        return await taskCompletionSource.Task;
    }

    // There is no TaskCompletionSource<void> so we use a bool that we throw away.
    public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
        Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => 
        await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
}

一旦你这样做了,你需要做的就是使用新的 RunTaskAsync 方法让你的后台任务等待 UI 工作.

Once you do that, all you need to do is use the new RunTaskAsync method to have your background task await on the UI work.

我们假设这是需要在 UI 线程中运行的方法.注意调试语句,这将有助于遵循流程:

Let's pretend that this is the method that needs to run in the UI thread. Pay attention to the debug statements, which will help follow the flow:

public static async Task<string> ShowMessageAsync()
{
    // Set up a MessageDialog
    var popup = new Windows.UI.Popups.MessageDialog("Question", "Please pick a button to continue");
    popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 1"));
    popup.Commands.Add(new Windows.UI.Popups.UICommand("Button 2"));
    popup.CancelCommandIndex = 0;

    // About to show the dialog
    Debug.WriteLine("Waiting for user choice...");
    var command = await popup.ShowAsync();

    // Dialog has been dismissed by the user
    Debug.WriteLine("User has made a choice. Returning result.");
    return command.Label;
}

要从后台线程等待它,您可以使用 RunTaskAsync:

To await that from your background thread, this is how you would use RunTaskAsync:

// Background thread calls this method
public async void Object_Callback()
{
    Debug.WriteLine("Object_Callback() has been called.");

    // Do the UI work, and await for it to complete before continuing execution
    var buttonLabel = await Dispatcher.RunTaskAsync(ShowMessageAsync);
    
    Debug.WriteLine($"Object_Callback() is running again. User clicked {buttonLabel}.");
}

输出如下所示:

Object_Callback() 已被调用.

Object_Callback() has been called.

等待用户选择...

用户已做出选择.返回结果.

User has made a choice. Returning result.

Object_Callback() 再次运行.用户点击了按钮 1.

Object_Callback() is running again. User clicked Button 1.

这篇关于RunAsync - 如何等待 UI 线程上的工作完成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆