Beetlejuice Beetlejuice - 1 month ago 5
C# Question

Verify if there is any async task running

I have a situation that the user just can close the windows when all async task finished.

How can I do that?

private async void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "starting process...";
await Task.Delay(2000);//some process 1
await Task.Delay(2000);//some process 2
await Task.Delay(2000);//some process 3
textBox1.Text = "Now we can close the form!";
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
?? check for async tasks end.
}


Is there any way to check if there is some task running, without actually having a property pointing to that?

Answer

You can save them on a dictionary so you can inspect them when attempting to close the form. You can also use Task.WhenAll to wait for them to finish, in the same FormClosing event handler.

private IDictionary<int, Task> _currentlyRunning = new Dictionary<int, Task>();

private async Task ExecuteTask(Task someTask)
{
    try 
    { 
        _currentlyRunning.Add(someTask.Id, someTask);
        await someTask;
    }
    finally
    {
       _currentlyRunning.Remove(someTask.Id);
    }
}

private async Task<TResult> ExecuteTask<TResult>(Task<TResult> someTask)
{
    try 
    { 
        _currentlyRunning.Add(someTask.Id, someTask);
        return await someTask;
    }
    finally
    {
       _currentlyRunning.Remove(someTask.Id);
    }
}

private async void button1_Click(object sender, EventArgs ea)
{
    await ExecuteTask(Task.Delay(2000)); //Some process 1
    await ExecuteTask(Task.Delay(2000)); //Some process 2
    // Do something
}

private async void button2_Click(object sender, EventArgs ea)
{
    int result = await ExecuteTask(SomeAsyncProcessThatReturnInt()); //Some process 3
    // Handle result
}

private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // You can:

    // Start waiting for all tasks to finish
    Task waiting = Task.WhenAll(_currentlyRunning.Select(t => t.Value).ToArray());

    textBox1.Text = "Waiting for all processes to finish";

    // Wait
    await waiting;

    textBox1.Text = "All good!"

    // Everything's done. Now you can close
    //...


   // Or

   // Check if there are any tasks running
   if (_currentlyRunning.Any())
   {
        textBox1.Text = "Not so fast! Some tasks haven't finished yet";
        ea.Cancel = true
   }
}
Comments