考虑在UI线程上运行的此代码:
dividends = await Database.GetDividends();
if (IsDisposed)
return;
//Do expensive UI work here
earnings = await Database.GetEarnings();
if (IsDisposed)
return;
//Do expensive UI work here
//etc...
Run Code Online (Sandbox Code Playgroud)
请注意,每次await我也检查IsDisposed.这是必要的,因为说我await长时间跑步Task.同时,用户在完成之前关闭表单.在Task将完成并运行一个试图访问已释放的窗体上的控件延续.发生异常.
有没有更好的方法来处理这个或简化这种模式?我await在UI代码中使用自由,IsDisposed如果我忘记的话,每次都要检查它并且容易出错.
编辑:
有一些提议的解决方案不符合要求,因为它们会改变功能.
这会让用户感到沮丧.而且它仍然允许发生可能昂贵的GUI工作,这是浪费时间,伤害性能并且不再相关.在我几乎总是在做背景工作的情况下,这可以防止表格在很长一段时间内关闭.
这具有阻止表单关闭的所有问题,除非不会使用户感到沮丧.执行昂贵GUI工作的延续仍将继续.它还增加了所有任务完成时的跟踪复杂性,然后在隐藏时关闭表单.
CancellationTokenSource在表单关闭时取消所有任务这甚至没有解决问题.事实上,我已经这样做了(浪费背景资源也没有意义).这不是解决方案,因为我仍然需要检查IsDisposed由于隐式竞争条件.以下代码演示了竞争条件.
public partial class NotMainForm : Form
{
private readonly CancellationTokenSource tokenSource = new CancellationTokenSource();
public NotMainForm()
{
InitializeComponent();
FormClosing += (sender, args) => tokenSource.Cancel();
Load += …Run Code Online (Sandbox Code Playgroud)