У меня есть приложение, которое выполняет некоторые фоновые задачи (прослушивание и чтение сети) в отдельном файле Thread
. Однако кажется, что поток не прерывается/не прерывается, когда я закрываю приложение (нажмите кнопку «x» в заголовке). Это потому, что основной подпрограммой Thread является while(true) {...}
? Какое решение здесь? Я искал некоторый флаг «прерывания» для потока в качестве условия для цикла «пока», но не нашел.
Поток не прерывается при закрытии приложения
Ответы (5)
Самый простой способ — установить свойство IsBackground. потока в true. Это предотвратит сохранение приложения открытым. Приложение завершается, когда завершаются все нефоновые потоки.
Более контролируемый способ остановить поток — отправить ему сообщение для корректного закрытия и убедиться, что он завершен, прежде чем разрешить завершение основного потока.
Я бы не рекомендовал использовать метод Thread.Abort
. Это имеет ряд проблем, одна из которых заключается в том, что не гарантируется завершение потока. Из документации:
Вызов этого метода обычно завершает поток.
Акцент мой.
while (stayAlive)
вместо true
намного чище, даже если для очистки цикла может потребоваться несколько дополнительных секунд.
- person user7116; 18.05.2010
Вы всегда можете форсировать проблему:
class Program
{
public static void Main()
{
// ... do stuff
Environment.Exit(Environment.ExitCode);
}
}
Лучший подход — установить для свойства Thread.IsBackground значение true, как уже упоминал Марк.
Вы можете улучшить цикл while(true) до
void DoWork() {
while(!ShouldIQuitManualResetEvent.WaitOne(0)) {
// do something
}
IDidQuitManualResetEvent.Set()
}
Чуть более изящный, короткий от имени идентификатора.
Ну, вместо while(true)
, может быть, вам стоит:
while(appIsRunning)
{
}
И, на заключительном мероприятии для вашей формы,
appIsRunning = false;
thread.Join(2000);
где последняя строка предназначена только для того, чтобы убедиться, что вы ждете, пока поток завершится чисто. Есть много других способов принудительно завершить цепочку, но проблема заключается именно в этом: вы не хотите форсировать события, вы хотите, чтобы они происходили как можно более естественно.
После присоединения вы можете проверить статус потока, чтобы убедиться, что он завершен. Если это не так, тогда (и только тогда) принудительно завершите его с помощью прерывания и, возможно, уведомите вашего пользователя (или запишите запись в журнал), что что-то не закончилось так, как должно.
volatile
или lock
или какой-либо другой метод синхронизации.
- person Mark Byers; 18.05.2010
Вы можете начать свою тему как:
ThreadPool.QueueUserWorkItem(DoStuff, input)
И это будет прервано автоматически с закрытием приложения.