Waiting for a task to complete before closing the form

How can I make the FormClosing event handler (which runs on the user interface thread) wait for a task that invokes in the same form to complete?

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        cancelUpdater.Cancel(); // CancellationTokenSource
        if (!updater.IsCompleted)
        {
            this.Hide();
            updater.Wait(); // deadlock if updater task is inside invoke
        }
    }
    private void Form1_Shown(object sender, EventArgs e)
    {
        cancelUpdater = new CancellationTokenSource();
        updater = new Task(() => { Updater(cancelUpdater.Token); });
        updater.Start();
    }
    void Updater(CancellationToken cancellationToken)
    {
        while(!cancellationToken.IsCancellationRequested)
        {
            this.Invoke(new Action(() => {
                ...
            }));
            //Thread.Sleep(1000);
        }
    }
+4
source share
1 answer

The right way to handle this is to cancel the event Close, and then close the form for real when the task completes. It might look something like this:

private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    cancelUpdater.Cancel(); // CancellationTokenSource
    if (!updater.IsCompleted)
    {
        this.Hide();
        e.Cancel = true;
        await updater;
        this.Close();
    }
}

Now in your comments you wrote:

the Close () method called by form B will immediately return and the changes that form B will cause the update to fail

- , " B", , - Form1. , " B", Form1 . , , , , , , .


, UI. , , - . , , . , , .

, .

, " B" , , BeginInvoke() Invoke() ( , " " , ). , , , , . .


, , , , , , System.Windows.Forms.Timer. , .

:

Timer . timer1. Interval 1000 , . , Updater() , timer1_Tick(object sender, EventArgs e) Tick.

, :

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    timer1.Stop();
}

private void Form1_Shown(object sender, EventArgs e)
{
    timer1.Start();
}

void timer1_Tick(object sender, EventArgs e)
{
    // All that will be left here is whatever you were executing in the
    // anonymous method you invoked. All that other stuff goes away.
    ...
}

System.Windows.Forms.Timer Tick , . FormClosing, . . , , Tick , Invoke() .


, - , . , , , , .

+5

All Articles