[英]Blocking on async with Thread.Sleep() & Task.Yield()
我知道在大多数情况下,阻止异步代码是不被批准的。
但是,我有一个WPF应用程序执行后台任务。 当用户关闭窗口时,应取消此任务,并延迟关闭窗口,直到取消和随后的清理完成为止。 同时,任何其他用户输入都应被阻止。
经过一番搜索和尝试,我想到了以下代码:
ViewModel.cs:
async void RunTaskAsync()
{
_cancelTknSource = new CancellationTokenSource();
try {
await Task.Run(/*...long running calculation...*/, _cancelTknSource.Token);
}
catch (OperationCanceledException) { }
finally {
/*...cleanup...*/
_cancelTknSource.Dispose();
_cancelTknSource = null;
}
}
async Task CancelAsync()
{
_cancelTknSource?.Cancel();
while (_cancelTknSource != null) {
Thread.Sleep(10);
await Task.Yield(); //prevents dead-lock
}
}
Window.xaml.cs:
async void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
await DataContext.CancelAsync();
Close();
}
(所有这些方法都是从UI线程调用的)
这是好习惯吗? 如果没有,有哪些替代方案?
在没有错误处理和清理的情况下(例如,将_cancelTknSource和_runningTask设置为null),以下代码应该可以完成。 但是您仍然必须在Window_Closing和窗口实际关闭之间阻止一些UI功能。
async void RunTaskAsync()
{
using(_cancelTknSource = new CancellationTokenSource())
{
_runningTask =Task.Run(/*...long running calculation...*/, _cancelTknSource.Token);
await _runningTask;
}
}
Task CancelAsync()
{
_cancelTknSource?.Cancel();
return _runningTask;
}
Window.xaml.cs:
async void Window_Closing(object sender, CancelEventArgs e)
{
e.Cancel = true;
await DataContext.CancelAsync();
Close();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.