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

查看:161
本文介绍了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?

修改

我原来的问题所承担的premature延续由API的设计造成的,所以这里的真正的问题。

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

在等待 Dispatcher.RunAsync 使用异步委托,使用等待委托的code内时,当等待出现连续遇到,而不是当工作​​已完成。我怎么能等待工作完成?

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.

推荐答案

我发现了一个的微软的GitHub库:如何等待从后台线程发出了UI的任务。

I found the following suggestion on a Microsoft github repository: How to await a UI task sent from a background thread.

首先,定义为CoreDispatcher这种扩展方法。

First, define this extension method for the 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 方法来等待你的任务。这里是你如何使用它一个简单的例子。

Once you do that, all you need to do is use the new RunTaskAsync method to await on your task. Here is a quick example on how you can use it.

让我们pretend,这是需要在UI线程运行的方法。一些调试语句pretty简单的东西来帮助遵循的流程:

Let's pretend that this is the method that needs to run in the UI thread. Pretty simple stuff with some debug statements to help follow the flow:

public static async Task<string> ShowMessageAsync()
{
    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;

    Debug.WriteLine("Waiting for user choice...");
    var command = await popup.ShowAsync();

    Debug.WriteLine("User has made a choice. Returning result.");
    return command.Label;
}

要等待,从你的后台线程,这是你会做什么:

To await that from your background thread, this is what you would do:

// Background thread calls this method
public async void Object_Callback()
{
    Debug.WriteLine("Object_Callback() has been called.");
    var buttonLabel = await Dispatcher.RunTaskAsync(ShowMessageAsync);
    Debug.WriteLine($"Object_Callback() is running again. User clicked {buttonLabel}.");
}

然后输出看起来是这样的:

The output then looks like this:

Object_Callback()被调用。

Object_Callback() has been called.

正在等待用户选择...

Waiting for user choice...

用户已经做出了选择。返回结果。

User has made a choice. Returning result.

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

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

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

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