繁体   English   中英

使用Thread.Sleep()和Task.Yield()阻止异步

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM