1

I'm writing an async event handler for a windows form but I'm not experienced with the way C# handles certain scenarios, as closing the form during a async processing triggered by an async event handler in this case.

Closing the form in question does not terminate the whole program, as the form was initialized by another form (the "main" form).

That's what the code I'm writing looks like:

private void async btn_ButtonClick(...){
   aLabel.Text = "Validating something ...";
   var isValid = await IsSomethingValid(...);
   if (isValid)
       aLabel.Text = "It's valid";

   else{
       aLabel.Text = "Sending email ...";
       await SendEmail(...);
       aLabel.Text = "Email sent";
   }
}

I've done some tests and even placing a long Thread.Sleep in SendEmail (before when it actually sends the email) and closing the form during that sleep the email ends up being sent.

Why is it so?

Would an async query also be executed even after closing its parent process?

Tiago Dall'Oca
  • 329
  • 3
  • 15
  • Unless you stop the task which you awating for it will continue until exception or end. Once you call `SendEmail()` it will try to complete, unless you [provide cancellation](https://stackoverflow.com/q/10134310/1997232) (then you can perform cancel in form closing event). – Sinatr Jan 10 '19 at 12:30
  • even if he stop this would obviously no help if data were send to server already – Selvin Jan 10 '19 at 12:31
  • Do you see this as a problem? Usually it would be considered a feature. – bommelding Jan 10 '19 at 12:42
  • 2
    `async void` is usually described as "Fire and Forget". Well, you've fired and just because you're forgetting about it doesn't mean it doesn't carry on. – Damien_The_Unbeliever Jan 10 '19 at 13:17
  • This works as well as the infamous Application.DoEvents(). Which is known to sometimes not blow up a program with an inscrutable exception. You'll get away with it because the Text property is somewhat special, it doesn't actually try to update the Label control after it is disposed. Not exactly a feature. – Hans Passant Jan 10 '19 at 13:43

1 Answers1

2

When an async method such as your event handler hits an await, it will return to the caller. Once the awaitable method (IsSomethingValid or SendEmail) has returned, the remainder of the async method (btn_ButtonClick) will be executed.

The fact that you close the form before the awaitable method (IsSomethingValid or SendEmail) has returned doesn't stop the remainder of the async method (btn_ButtonClick) from being executed.

If you don't want to do anything after the form has been closed, you could use a flag that keeps track of whether it has been closed, e.g.:

public Form1()
{
    InitializeComponent();
    FormClosed += Form1_FormClosed;
}

private async void btn_ButtonClick(object sender, EventArgs e)
{
    var isValid = await IsSomethingValid();
    if (isValid && !_isClosed) //<--
    {
        MessageBox.Show("!");
    }
}

private void Form1_FormClosed(object sender, FormClosedEventArgs e) => _isClosed = true;

private async Task<bool> IsSomethingValid()
{
    await Task.Delay(5000);
    return true;
}

Would an async query also be executed even after closing its parent process?

No, or at least not the continuation. If you send an email and exit the application, this doesn't necessarily stop the email from being sent.

mm8
  • 163,881
  • 10
  • 57
  • 88