我了解在大多数情况下,阻止异步代码被拒绝。
但是,我有一个执行后台任务的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线程调用的)
这是好习惯吗? 如果没有,有哪些替代方案?
答案 0 :(得分:0)
没有错误处理和清理(例如,将_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();
}