Application.DoEvents в событии FormClosing

Я реализовал свой собственный ThreadManager, который безупречно работал во время моих тестов. Когда пользователь хочет закрыть приложение, закрытие приостанавливается до тех пор, пока не будут завершены все потоки или они не выберут завершение приложения без ожидания (по прошествии 30 секунд).

Мне нужно уточнить, может ли использование Application.DoEvents() быть опасным в событии FormClosing. Должен ли я использовать его или найти другой способ ожидания выхода потоков?

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

person iCantSeeSharp    schedule 25.07.2012    source источник
comment
Зачем беспокоить пользователя? Они знают, что происходит? В большинстве своих приложений я просто немедленно выхожу из приложения, потому что нет причин не делать иначе. В странном случае, когда мне нужно убедиться, что какой-то файл закрыт или соединение с БД отключено, я просто сворачиваю приложение и жду с таймером сообщения/сообщений об отключении потока или BeginInvokes() или чего-то еще.   -  person Martin James    schedule 25.07.2012
comment
Действительно, есть соединение с БД, которое нужно разорвать, а также есть WebBrowser или WatiN вызовы, которые должны возвращаться, поэтому убивать приложение не рекомендуется. Минимизация на самом деле не сильно отличается от отображения формы ожидания.   -  person iCantSeeSharp    schedule 25.07.2012


Ответы (1)


Я бы рекомендовал поместить ваше условие ожидания в другой поток. Отображение модального диалога из метода OnFormClosing. В этом диалоговом окне запустите рабочий поток, например, используя класс BackGroundWorker и закрыть это диалоговое окно, когда ожидание завершено.

Дополнительная тема возможные недостатки вызова метода Application.DoEvents

person Jacob Seleznev    schedule 25.07.2012
comment
Итак, это, по сути, означает e.Cancel = true в FormClosing, верно? Редактировать: Нет, это не так. Я понял это на 100% сейчас. - person iCantSeeSharp; 25.07.2012