Поток не прерывается при закрытии приложения - PullRequest
15 голосов
/ 18 мая 2010

У меня есть приложение, которое выполняет некоторые фоновые задачи (прослушивание и чтение по сети) в отдельном Thread. Однако кажется, что поток не прерывается / прерывается, когда я закрываю приложение (нажмите кнопку «x» на заголовке). Это потому, что основная подпрограмма Thread - while(true) {...}? Какое решение здесь? Я искал какой-то флаг «прерывание» для потока в качестве условия для цикла «пока», но не нашел ни одного.

Ответы [ 5 ]

21 голосов
/ 18 мая 2010

Самый простой способ - установить для свойства IsBackground потока значение true. Это предотвратит сохранение приложения открытым. Приложение завершается, когда завершаются все не фоновые потоки.

Более контролируемый способ остановить поток - это отправить ему сообщение о чистом завершении работы и убедиться, что он завершился, прежде чем позволить завершить основной поток.

Метод, который я бы не рекомендовал, это вызвать Thread.Abort. Это имеет ряд проблем, одна из которых заключается в том, что не гарантируется завершение потока. Из документации:

Вызов этого метода обычно завершает поток.

Акцент мой.

3 голосов
/ 18 мая 2010

Вы всегда можете форсировать проблему:

class Program
{
    public static void Main()
    {
        // ... do stuff
        Environment.Exit(Environment.ExitCode);
    }
}

Лучший подход - установить для свойства Thread.IsBackground значение true, как уже упоминалось Марком.

1 голос
/ 18 мая 2010

Вы можете улучшить цикл while (true) до

void DoWork() {
    while(!ShouldIQuitManualResetEvent.WaitOne(0)) {
      // do something
    }
    IDidQuitManualResetEvent.Set()
}

Немного более изящный, короткий от имен идентификаторов.

0 голосов
/ 18 мая 2010

Вы можете начать свою тему как:

ThreadPool.QueueUserWorkItem(DoStuff, input)

И оно будет автоматически отменено при закрытии приложения.

0 голосов
/ 18 мая 2010

Ну, вместо while(true), может быть, вам стоит:

while(appIsRunning)
{
}

И, на заключительном мероприятии для вашей формы,

appIsRunning = false;
thread.Join(2000);

где последняя строка только для того, чтобы убедиться, что вы ожидаете, пока поток не завершит чистое окончание. Есть много других способов навязать конец потоку, но проблема только в этом: вы не хотите, чтобы заставлял вещи, вы хотите, чтобы они происходили настолько естественно, насколько это возможно.

После объединения вы можете проверить состояние потока, чтобы увидеть, завершилось ли оно. Если этого не произойдет, , тогда (и только тогда) принудительно завершит свою работу с прерыванием и, возможно, уведомит вашего пользователя (или запишет запись в журнал), что что-то не закончилось так, как должно.

...