2010-05-17 4 views
15

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

ответ

21

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

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

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

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

Emphasis mine.

+1

+1 к методу сообщения.'while (stayAlive)' вместо 'true' намного чище, даже если это потенциально занимает несколько лишних секунд, чтобы цикл прояснился. – user7116

0

Ну, а while(true), может быть, вы должны:

while(appIsRunning) 
{ 
} 

И в случае закрытия для формы,

appIsRunning = false; 
thread.Join(2000); 

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

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

+0

Да, но не забудьте использовать 'volatile' или' lock' или какой-либо другой метод синхронизации. –

+0

@Mark: может быть, здесь совершенно неправильно, но так как ребенок Thread только читает, а основной поток записывает только, есть ли шанс на ошибку? –

+1

Без синхронизации не гарантируется, что изменение в appIsRunning из одного потока будет видимым в другом потоке. Вы можете прочитать здесь: http://timl.net/2009/03/volatile-memory.html –

1

Вы могли бы улучшить время (истина), петля для

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

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

3

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

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

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

0

Вы можете начать нить, как:

ThreadPool.QueueUserWorkItem(DoStuff, input) 

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

Смежные вопросы