Question

I have implemented my custom ThreadManager which has been working flawlessly during my tests. When user wants to close the application, the closing is suspended until all threads exit or they select to end the application without waiting (after 30 seconds have passed).

What I need to clarify is if using Application.DoEvents() could be dangerous in FormClosing event. Shall I use it or find another way of waiting for threads to exit?

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    // save settings before exit
    Properties.Settings.Default.Save();

    // Update program about intention
    Program.ApplicationClosing = true;

    try
    {
        // Inform user with friendly message
        ShowModalWaitForm("Application is closing.");

        // Keep the timestamp in order to keep track of how much time has passed since form closing started
        DateTime startTime = DateTime.Now;

        // Wait for all threads to die before continuing or ask user to close by force after 30 seconds have passed
        // In case user prefers to wait the timer is refreshed
        int threadsAlive;
        do
        {
            if (_threadManager.TryCountAliveThreads(out threadsAlive) && threadsAlive > 0)
            {
                Application.DoEvents();
                Thread.Sleep(50);
            }

            TimeSpan timePassed = DateTime.Now - startTime;
            if (timePassed.Seconds > 30)
            {
                if (ShouldNotWaitThreadsToExit())
                {
                    break; // Continue with form closing
                }
                else
                {
                    startTime = DateTime.Now; // Wait more for threads to exit
                }
            }
        } while (threadsAlive > 0);
    }
    catch (Exception ex)
    {
        _logger.ErrorException("MainForm_FormClosing", ex);
    }
    finally
    { 
        HideWaitForm(); 
    }
}


private bool ShouldNotWaitThreadsToExit()
{
    return MessageBox.Show(@"Press ""OK"" to close or ""Cancel"" to wait.", "Application not responding ", MessageBoxButtons.OKCancel) == DialogResult;
}
Was it helpful?

Solution

I'd recommend putting your wait condition in another thread. Display a modal dialog from OnFormClosing method. Inside this dialog start worker thread e.g using BackGroundWorker class and dismiss this dialog when waiting finished.

Bonus topic possible drawbacks of calling Application.DoEvents Method

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top