简体   繁体   中英

Cannot access a disposed object exception when using async await in a windows forms application

I'm playing a bit with async await, and tried to replace a backgroundworker with it.

The following code however will throw a exception when i close the form, and the task is still running: Cannot access a disposed object. Object name: '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));
    }
}

I do understand that because of the short delay when writing to the textbox, it'll try to write when the textbox is already disposed.

If i just remove the async/await from the click event, there is no error anymore when closing the form.

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

Question: Is it correct just to remove await async from the click eventhandler, and what is the difference there?

Are there situations when a forms eventhandler should be async?

Is it correct just to remove await async from the click eventhandler, and what is the difference there?

It's correct if your asynchronous work ( Task.Delay ) is meaningless. The difference is that a synchronous handler is completed immediately (synchronously), so the form cannot possibly close before textBox is updated.

Are there situations when a forms eventhandler should be async?

Yes: if it has asynchronous work to do. In other words, make the event handler async if and only if you want to use await in that method.

-If you do not care if it is blocking then do not use async/await.

-If you do not want the operation to complete if they close the form, but you also do not want the operation to be blocking you will need to use a CancellationToken.

-If you want the work to complete even if the form is closed and you do not want it to be blocking you will need to use async/await and:

Either do not allow the form to close during the operation or... Check Disposing & IsDisposed before setting the text, however even when checking Disposing & IsDisposed if you get the exact wrong timing you can still get the error because you cannot know when control will return... So additionally catch the disposed object error specifically and throw it away (This is okay in this case because you obviously don't care if the textbox is updated anymore because the form is closed. You can log the error if you wish.).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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