简体   繁体   English

当用户关闭在异步事件处理程序中执行异步任务的表单时会发生什么?

[英]What happens when the user closes a form performing an async task in an async event handler?

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. 我正在为Windows窗体编写一个异步事件处理程序,但是我对C#处理某些情况的方式并不熟悉,因为在这种情况下,在异步事件处理程序触发的异步处理过程中关闭了窗体。

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. 我已经进行了一些测试,甚至在SendEmail放置了一个很长的Thread.Sleep (在它实际发送电子邮件之前),并在睡眠期间关闭了表单,最终电子邮件被发送了。

Why is it so? 为什么会这样呢?

Would an async query also be executed even after closing its parent process? 即使关闭了父进程,异步查询也会执行吗?

When an async method such as your event handler hits an await , it will return to the caller. async方法(例如事件处理程序)命中await ,它将返回给调用方。 Once the awaitable method ( IsSomethingValid or SendEmail ) has returned, the remainder of the async method ( btn_ButtonClick ) will be executed. 一旦返回了可等待的方法( IsSomethingValidSendEmail ),将执行async方法的其余部分( btn_ButtonClick )。

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. 您在等待方法( IsSomethingValidSendEmail )返回之前关闭表单的事实并没有阻止async方法的其余部分( btn_ButtonClick )执行。

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, eg: 如果关闭表单后不想执行任何操作,则可以使用一个标志来跟踪表单是否已关闭,例如:

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. 如果您发送电子邮件并退出应用程序,则不一定阻止电子邮件发送。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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