DelegateCommand异步等待与Task.Run UI锁定

时间:2020-04-04 07:33:22

标签: c# wpf async-await command task

我希望我的UI在单击按钮后显示加载叠加层。

选项1

MyCommand = new DelegateCommand(() => Task.Run(MyLongRunningTask);

private async Task MyLongRunningTask() {
    IsLoading = true;
    Thread.Sleep(5000);
    IsLoading = false;
}

选项2

MyCommand = new DelegateCommand(MyLongRunningMethod);

private async void MyLongRunningMethod() {
    IsLoading = true;
    Thread.Sleep(5000);
    IsLoading = false;
}

选项1有效,选项2无效。我很满意,尽管我不明白为什么。 但我真的想避免必须将每个执行都包装到()=> Task.Run(...)。

由于异步void似乎不是一个好主意,所以我想继续使用任务。但是我想缩短语法,所以我想疯狂地尝试,但是我不知道如何将()=> Task.Run(..)放在从DelegateCommand派生的方法或类中。

为什么不编译?

    private DelegateCommand GetAsyncCommand(Task t)
    {
        return new DelegateCommand(() => Task.Run(t));
    }

与此类似的任何事情都会导致编译时错误或我不得不调用

MyCommand = GetAsyncCommand(MyLongRunningTask());

由于()括号,它立即在实例化时执行我的任务。

这似乎让我很困惑。如果我必须将所有长时间运行的任务包装到此结构中,为什么我不能构建一个更智能的命令来为任务分配给我呢?

编辑:我只是注意到选项1可能不会锁定UI,但是会吞噬异常的可怕内容。

我如何设置一个不会阻塞UI并正常引发任何异常的命令?

1 个答案:

答案 0 :(得分:2)

Thread.Sleep()锁定当前线程,而不管它在哪里:同步或异步方法。异步方法还有另一种暂停执行的方式-await Task.Delay()

asyncThreading不负责,async实现了一个state mashine,该代码执行代码以异步方式将其按等待的部分分割。 Task负责线程。

替换

Thread.Sleep(5000);

使用

await Task.Delay(5000);

请注意,async void是不好的做法。 Look