Можно ли вызывать thread.Abort(), когда форма закрывается? Если нет, то достаточно ли глобального флага?

Прежде всего, Thread.Abort() - зло - понял! Теперь позвольте мне объяснить мою ситуацию...

Ситуация:

У меня есть приборная панель, которая отображает только текущее состояние работы для пользователя. Он выполняет различные запросы выбора к базе данных Sql Server и выполняет некоторые вычисления, которые в конечном итоге отображаются пользователю на панели инструментов. Пользователь может открыть несколько панелей одновременно. У меня есть нить таймера, которая обновляет приборную панель каждые несколько секунд. Этот поток таймера порождает другой поток (фактически работает с очередями в пуле потоков) для выполнения длительных вычислений / запросов.

Эта проблема:

Когда пользователь нажимает X, чтобы закрыть окно Dashboard, оно должно быть закрыто сразу (скажем, через секунду я думаю, что 2 секунды это слишком долго). Поэтому я использую этот код:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        _timerThread.Abort();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // we're on the timer thread now

        try
        {
            RefreshUi();
        }
        catch (ThreadAbortException)
        {
            System.Threading.Thread.ResetAbort();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

Проблема иногда в том, что ThreadAbortException перехватывается, а иногда нет. Я нахожу, что это в основном непослушно, когда выполняется запрос.

[ОБНОВЛЕНИЕ] Я недавно обнаружил, что могу поймать исключение ThreadAbortException, если проверю исключение.

Вопросы:

  1. Можно ли использовать Thread.Abort () в этом случае? Если да, то как ВСЕГДА перехватить исключение ThreadAbortException, чтобы пользователь не увидел его при закрытии формы? (из того, что я прочитал, я не думаю, что это возможно)
  2. Если использование Thread.Abort () не совсем нормально (я думаю, что большинство из вас ответит на него), то вот мои другие проблемы с использованием "глобального логического флага", чтобы сообщить потоку (-ам), когда завершать работу.
    • Я обеспокоен тем, что потоки не остановятся в течение 1 секунды. (Например, у меня могут быть некоторые запросы, выполнение которых занимает 1-2 секунды)
    • Мне придется загромождать свой код с помощью: if(shouldShutdown) операторов.
    • Должен ли я сделать флаг shouldShutdown статическим, чтобы все мои классы могли его использовать? Будет ли это проблемой, если пользователь сможет одновременно открыть несколько панелей? (Я обеспокоен тем, что статическая переменная является общей для всех инструментальных панелей. Этого я определенно не хочу.)
    • Когда рабочие потоки видят, что они должны завершить работу, они должны выдать исключение или просто вернуться? Если они просто вернутся, то мне придется добавить еще больше проверок if (shouldShutdown), потому что некоторые функции могут возвращать false. Если выбрасывать исключение нормально, какое исключение вы рекомендуете? Кастом?

Спасибо

1 ответ

Решение

Правильный способ сделать это будет

  1. Выполнение всех запросов к серверу SQL асинхронно
  2. имеющий ManualResetEvent обрабатывается в фоновых потоках и запускается из основного потока, когда пора закрываться.
  3. Прерывание SQL-запросов в AutoResetEvent обработчики и изящно выходящие потоки
  4. Создание GUI закрывает окна параллельно с выходом из потоков, чтобы они не зависели друг от друга.
  5. Если закрытие панели мониторинга означает выход из процесса, было бы хорошо дождаться завершения всех потоков при закрытых окнах.
Другие вопросы по тегам