我希望我的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并正常引发任何异常的命令?
答案 0 :(得分:2)
Thread.Sleep()
锁定当前线程,而不管它在哪里:同步或异步方法。异步方法还有另一种暂停执行的方式-await Task.Delay()
。
async
对Threading
不负责,async
实现了一个state mashine,该代码执行代码以异步方式将其按等待的部分分割。 Task
负责线程。
替换
Thread.Sleep(5000);
使用
await Task.Delay(5000);
请注意,async void
是不好的做法。 Look。