У меня есть небольшая форма, которая создает два фоновых рабочих потока, которые прослушивают сообщения от двух отдельных серверных процессов. Когда пользователь пытается закрыть форму, я обрабатываю событие OnFormClosing (или они могут щелкнуть пункт меню «Выход»), которое вызывает CancelAsync () в обоих потоках. Затем форма ожидает, пока свойство IsBusy для обоих потоков не станет "FALSE", прежде чем вызывать Environment.Exit (0).

Вот загвоздка: из этой формы пользователь может запустить отдельное приложение. Это делается с помощью Process.Start при нажатии определенной кнопки. Если пользователь создал новый процесс через форму, а затем закрывает форму, вместо изящного выхода происходит сбой, и я получаю одно из этих сообщений об ошибке Windows. Application.Exit не работает, потому что он не закрывает форму по неизвестной мне причине. Я уверен, что оба потока завершены, потому что я обрабатываю событие RunWorkerCompleted для обоих потоков. Вот оболочка основного кода:

private void startProcess_buttonClick(sender, e)
{
      Process.Start(<process args>);
}


protected override OnFormClosing()
{
    e.Cancel = true;

    if (!thread1.IsBusy && !thread2.IsBusy)
       Environment.Exit(0);

    stopThreads();
}
private void stopThreads()
{
   if (thread1.IsBusy)
       thread1.CancelAsync();

   if (thread2.IsBusy)
       thread2.CancelAsync();
}

private void thread1_RunWorkerCompleted(sender, e)
{
       if (!thread2.IsBusy)
          Environment.Exit(0);
}


private void thread2_RunWorkerCompleted(sender, e)
{
       if (!thread1.IsBusy)
          Environment.Exit(0);
}

Любые идеи относительно того, что может вызвать сбой в Environment.Exit?

3
alexD 10 Окт 2010 в 02:33
Вы смотрели журнал событий? Будет записана точная ошибка.
 – 
Aliostad
10 Окт 2010 в 02:38
Вот что написано: «Тип события clr20r3; P1 ccs_wsdt.exe, P2 1.0.0.0. P3 4cb0eeb3. P4 system.windows.forms. P5 2.0.0.0. P6 471ebf68. P7 16c6. P8 159. P9 system.componentmodel.win32 . P10 NIL "Не знаю, как это интерпретировать. Код / приложение запускается в автономной сети, поэтому мне приходится вручную вводить все здесь.
 – 
alexD
10 Окт 2010 в 02:47

2 ответа

Лучший ответ

Пытаться

Application.Exit()

Поскольку вы используете Windows Forms. Я сам не делал тестовый пример, но я почти уверен, что API Winforms недовольны немедленным завершением процесса через среду, которая использует API ядра.

Я также нашел это: http://geekswithblogs.net/mtreadwell/archive/ 06.06.2004 / 6123.aspx

3
usr-local-ΕΨΗΕΛΩΝ 10 Окт 2010 в 03:55
Я пробовал application.Exit ... оно не выходит из моего приложения.
 – 
alexD
10 Окт 2010 в 04:04
На самом деле, после исправления некоторых других вещей, я снова попробовал Application.Exit, и он тоже вылетел.
 – 
alexD
10 Окт 2010 в 04:11
1
Можете ли вы где-нибудь поймать какое-нибудь исключение? Попробуйте подключиться к Application.ThreadException и выполнить MessageBox.Show (например, ToString), это может вам больше помочь!
 – 
usr-local-ΕΨΗΕΛΩΝ
10 Окт 2010 в 04:21
^^ Я попробовал это в этом руководстве: msdn.microsoft.com/en-us/library/… Мое приложение не улавливает никаких исключений, но, похоже, оно больше не дает сбоев ... Хотел бы я понять, почему. Собираюсь протестировать его еще немного и посмотреть, действительно ли он работает сейчас или просто еще не сломался случайно.
 – 
alexD
10 Окт 2010 в 04:51
У меня была такая же проблема, и я попробовал это решение, но теперь я дважды получаю сообщение о выходе! и надоело this.close (); но он ничего не дозирует
 – 
sam
21 Дек 2016 в 20:30

Как насчет

protected override OnFormClosing()
{
    e.Cancel = true;

    if (!thread1.IsBusy && !thread2.IsBusy)
       this.Close();

    stopThreads();
}
private void thread1_RunWorkerCompleted(sender, e)
{
       if (!thread2.IsBusy)
          this.Close();
}
private void thread2_RunWorkerCompleted(sender, e)
{
       if (!thread1.IsBusy)
          this.Close();
}
0
Ohad Schneider 13 Окт 2010 в 18:58