C# 在返回之前执行async命令

C# 在返回之前执行async命令,c#,.net,wpf,asynchronous,async-await,C#,.net,Wpf,Asynchronous,Async Await,我在.NET4.0应用程序中使用模板,其中一个页面需要执行异步命令,然后才能导航回另一个页面。同时,必须在命令运行时解锁UI线程。如果我这样做: public void OnNavigatingFrom(FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs e) { TaskEx.Run(() => { //Replace Sl

我在.NET4.0应用程序中使用模板,其中一个页面需要执行异步命令,然后才能导航回另一个页面。同时,必须在命令运行时解锁UI线程。如果我这样做:

    public void OnNavigatingFrom(FirstFloor.ModernUI.Windows.Navigation.NavigatingCancelEventArgs e)
    {
        TaskEx.Run(() =>
            {
                //Replace Sleep call by the async command execution
                System.Threading.Thread.Sleep(5000);
            }).Wait();}
OnNavigatingFrom在返回之前等待,但在此期间UI被阻止

关于如何在不同的上下文中执行异步代码并使OnNavigatingFrom“同步”运行,您有什么想法吗


编辑:有一个解决方案,没有结论性的答案

只需
等待
任务,而不使用
.Wait()


有关如何在.NET 4.0中等待的信息,请参见仅
等待
任务,而不是使用
.Wait()


有关如何在.NET 4.0中等待的信息,请参见以下内容:

public void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    // Fire and forget.
    Task.Run(() => MyCommandAsync());
}
以上是一种免责方法,相反,最好使用
async
wait

public async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    await MyCommandAsync();
}

以下是您需要做的:

public void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    // Fire and forget.
    Task.Run(() => MyCommandAsync());
}
以上是一种免责方法,相反,最好使用
async
wait

public async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    await MyCommandAsync();
}
一个页面在返回到另一个页面之前需要执行异步命令

这就是问题所在。用户界面不是异步的。在UI进行转换时,不能只将异步操作粘贴到混合中

这样想:作为一个用户,如果你决定导航回去,网络出现了问题,程序在导航回去时冻结了几秒钟,这是一个糟糕的用户体验,对吗?UI无法在更新期间等待异步工作

您可以做的是在允许用户返回之前完成工作。例如,您可以捕获用户返回的意图,并在操作进行时显示某种“请等待”UI,然后在操作完成后执行实际的导航

一个页面在返回到另一个页面之前需要执行异步命令

这就是问题所在。用户界面不是异步的。在UI进行转换时,不能只将异步操作粘贴到混合中

这样想:作为一个用户,如果你决定导航回去,网络出现了问题,程序在导航回去时冻结了几秒钟,这是一个糟糕的用户体验,对吗?UI无法在更新期间等待异步工作


您可以做的是在允许用户返回之前完成工作。例如,您可以捕获用户返回的意图,并在操作进行时显示某种类型的“请等待”UI,然后在操作完成后执行实际导航。

使用OnNavigatingFrom执行您的操作e.取消阻止返回。在操作完成后使用Frame.GoBack()

protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    if (Current.HasModifications())
    {
        e.Cancel = true;
        await Current.Save().ContinueWith((t) =>
        {
            //Go Back after the Operation has finished
            Frame.GoBack();
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    else
    {
        base.OnNavigatingFrom(e);
    }
}

使用on导航from完成您的任务e.取消阻止返回。在操作完成后使用Frame.GoBack()

protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    if (Current.HasModifications())
    {
        e.Cancel = true;
        await Current.Save().ContinueWith((t) =>
        {
            //Go Back after the Operation has finished
            Frame.GoBack();
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    else
    {
        base.OnNavigatingFrom(e);
    }
}

你知道等待是一个阻塞呼叫吗?我知道,我知道这是一个问题。那么,考虑到调用方法(OnNavigatingFrom)在操作完成之前无法返回,如何使其非阻塞呢?如果(且仅当)OnNavigatingFrom
方法是一个事件处理程序,您可以将其设置为
公共异步void
(感谢Stephen Cleary阅读了大量文献)。这将允许您使用
wait
。例如,
wait DoSomethingAsync()。调用方法在等待的任务完成之前不会返回可能有什么用处?:@GeoffJames您说的对,调用方法在任务完成之前不会返回。但是,导航会立即执行,无需等待函数返回。我认为原因在于WPF模板框架导航的现代UI并不等待完成。有什么想法吗?你知道等待是一个阻塞呼叫吗?我知道,我知道这是一个问题。那么,考虑到调用方法(OnNavigatingFrom)在操作完成之前无法返回,如何使其非阻塞呢?如果(且仅当)OnNavigatingFrom
方法是一个事件处理程序,您可以将其设置为
公共异步void
(感谢Stephen Cleary阅读了大量文献)。这将允许您使用
wait
。例如,
wait DoSomethingAsync()。调用方法在等待的任务完成之前不会返回可能有什么用处?:@GeoffJames您说的对,调用方法在任务完成之前不会返回。但是,导航会立即执行,无需等待函数返回。我认为原因在于WPF模板框架导航的现代UI并不等待完成。有什么想法吗?这不起作用,因为OnNavigatingFrom是一个事件处理程序,简单地在方法头上添加async不会有任何区别。页面将立即返回。@IgorKondrasovas这是使用正确事件的问题。使用
wait
是等待异步操作的正确方法。您只是使用了错误的事件/模式。除了导航,您应该使用一个在完成后导航到新页面的命令,第一个表单将立即将执行的
MyCommandAsync
发布到线程池并返回,而第二个表单将在UI线程上运行,直到它到达第一个不完整的等待状态。这不起作用,因为OnNavigatingFrom是一个事件处理程序,简单地在方法头上添加async不会有任何区别。页面将立即返回。@IgorKondrasovas这是使用正确事件的问题。使用
wait
是等待异步操作的正确方法。您只是使用了错误的事件/模式。您应该使用导航到新pa的命令,而不是导航