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

时间:2019-01-10 12:25:12

标签: c# winforms asynchronous

我正在为Windows窗体编写一个异步事件处理程序,但是我对C#处理某些情况的方式并不熟悉,因为在这种情况下,在由异步事件处理程序触发的异步处理期间关闭窗体。

由于该表单是由另一种表单(“主”表单)初始化的,因此关闭有问题的表单不会终止整个程序。

这就是我正在编写的代码:

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";
   }
}

我已经进行了一些测试,甚至在Thread.Sleep中放置了一个长SendEmail(在它实际发送电子邮件之前),并且在睡眠期间关闭了该表单,最终电子邮件被发送了。

为什么会这样?

即使关闭其父进程后,也会执行异步查询吗?

1 个答案:

答案 0 :(得分:1)

当诸如事件处理程序之类的async方法命中await时,它将返回给调用方。返回了等待的方法(IsSomethingValidSendEmail之后,将执行async方法的其余部分(btn_ButtonClick)。

您在返回等待方法(IsSomethingValidSendEmail之前关闭表单的事实并没有停止async方法(btn_ButtonClick)的其余部分被执行。

如果您在表单关闭后不想执行任何操作,则可以使用一个标志来跟踪表单是否已关闭,例如:

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;
}
  

即使关闭其父进程后,也会执行异步查询吗?

否,或者至少不是延续。如果您发送电子邮件并退出应用程序,则不一定会阻止电子邮件的发送。