在Windows窗体应用程序中使用async await时无法访问已处置的对象异常

时间:2014-02-12 13:18:29

标签: c# .net asynchronous

我正在玩异步等待,并尝试用它替换背景工作者。

但是,当我关闭表单时,以下代码将抛出异常,并且任务仍在运行:无法访问已处置的对象。对象名称:'TextBox'

public Form1()
{
    InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
    await this.UpdateTextbox();
}
private async Task UpdateTextbox()
{
    for (int i = 0; i < 1000; i++)
    {
        //TaskDelay only simalates any async work
        await Task.Delay(50);
        textBox1.AppendText(string.Format("{0}{1}", i, Environment.NewLine));
    }
}

我确实理解由于写入文本框时的短暂延迟,它会在文本框已经处理时尝试写入。

如果我只是从click事件中删除async / await,则关闭表单时不再出现错误。

private  void button1_Click(object sender, EventArgs e)
{
     this.UpdateTextbox();
}

问题:从click事件处理程序中删除等待异步是否正确,那有什么区别?

是否存在表单事件处理程序应该是异步的情况?

2 个答案:

答案 0 :(得分:1)

  

仅从click eventhandler中删除等待异步是否正确,那有什么区别?

如果你的异步工作(Task.Delay)毫无意义,那是正确的。不同之处在于同步处理程序立即(同步)完成,因此在textBox更新之前表单不可能关闭。

  

是否存在表单事件处理程序应该是异步的情况?

是:如果它有异步工作要做。换句话说,当且仅当您想在该方法中使用async时,才设置事件处理程序await

答案 1 :(得分:1)

- 如果你不在乎它是否阻塞,那么不要使用async / await。

- 如果您不想在关闭表单时完成操作,但您也不希望操作被阻止,则需要使用CancellationToken。

- 如果您希望工作完成,即使表单已关闭且您不希望它被阻止,您将需要使用async / await和:

要么在操作过程中不允许表格关闭,要么...... 检查处置&amp;在设置文本之前进行排除,但即使检查Disposing&amp; IsDisposed如果你得到错误的时间你仍然可以得到错误,因为你不知道什么时候控制将返回... 因此,另外特别捕获已处理的对象错误并将其丢弃(在这种情况下这是可以的,因为您显然不在乎文本框是否因为表单已关闭而更新。如果您愿意,可以记录错误。)