2013-02-08 4 views
1

Я создаю поток для обработки метода блокировки в моем коде. таким образом, мой код может делать другие вещи помимо запуска этого метода блокировки.Как закрыть поток, содержащий метод блокировки в C#

вопрос: как я могу закончить нить правильно? мне нужно разблокировать метод блокировки, а затем завершить поток. или я могу просто прекратить нить, не беспокоясь о каком-либо уродливом сбое?

+0

Если вы не хотите, чтобы поток блокировался навсегда, не указывайте его. Это действительно настолько просто. Каждый раз, когда вы чувствуете, что вам нужно проникнуть извне и заставить поток что-то сделать, это просто доказывает, что вы не кодировали нить, чтобы делать то, что вам действительно нужно в первую очередь. –

ответ

0

Звонок yourthread.Abort(). Это не так, как в старые времена, когда это может привести к нарушению всего, когда ресурсы и блокировки не были выпущены, теперь это вызывает довольно хорошее исключение, которое может быть вызвано обычным способом ...

http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

Когда я говорю «нормальный путь», кажется, что нить прерывань исключение Авторемонтной прибавки (довольно хороший трюк)

http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx

, но это не помешает вам быть обливанием и сбрасывая другая большая вещь в блоке catch ...

+0

MSDN говорит, что Abort() обычно завершает поток. есть ли гарантированный способ закрыть его? =/ – CaTx

+0

Да, не обрабатывайте генерируемое исключение ... –

+0

Я вижу, спасибо большое. ^^ – CaTx

0

У вас есть варианты. Если вам не все равно, завершается ли операция, когда приложение идет вниз, вам может быть лучше использовать поток ThreadPool через QueueUserWorkItem или (как подсказывает Servy в комментариях) установите для свойства IsBackground вашего потока значение true, что позволит процессу для выхода без выхода потока.

Если вы заботитесь о завершении операции и/или о логике очистки, которую необходимо запустить при завершении работы, вероятно, вы действительно не хотите использовать Thread.Abort, по крайней мере, не как вашу стратегию goto. То, что я использую что-то похожее на это:

public abstract class DisposableThread : IDisposable 
{ 
    private ManualResetEvent exiting = new ManualResetEvent(false); 
    private Thread theThread; 
    private TimeSpan abortTimeout; 

    public DisposableThread(): 
     this(TimeSpan.FromMilliseconds(100)) 
    { 
    } 

    public DisposableThread(TimeSpan abortTimeout) 
    { 
     this.abortTimeout = abortTimeout; 
     theThread = new Thread((_) => ThreadProc()); 
    } 

    protected virtual void ThreadProc() 
    { 
     while(!exiting.WaitOne(0)) 
     { 
      WorkUnit(exiting); 
     } 
     ThreadCleanup(); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     exiting.Set(); 
     if (!theThread.Join(abortTimeout)) 
     { 
      // logme -- the thread didn't shutdown gracefully 
      theThread.Abort(); 
      while (!theThread.Join(1000)) 
      { 
       // logme -- the thread is doing something dumb in an exception handler 
      } 
     } 
     exiting.Dispose(); 
    } 

    // WorkUnit should return as quickly as safe if the exiting handle is set 
    // If it doesn't the thread will be aborted if it takes longer than abortTimeout 
    protected abstract void WorkUnit(WaitHandle exiting); 

    // override if you need to cleanup on exit 
    protected virtual void ThreadCleanup() { } 
} 

Что дает ваш поток шанс выйти грациозно и прерывает только если изящный выход из строя.

+2

Вы не хотите выполнять очень длительные операции в пуле потоков. Вы должны просто отметить поток, который вы создаете как фоновый поток, вместо «IsBackground = true». – Servy

+0

так, например, на веб-сайте, о котором я упоминал, как правильно закрыть 2 потока? =/ – CaTx

+0

Я не вижу здесь примера ... – Yaur

0

ОК, нашел свой ответ. Я должен объявить потоки, чтобы ссылки на них могли быть сделаны. затем я заканчиваю вложенный поток (который имеет HandleClientComm()), затем закрывает TCP_Client (если не null) и TCP_Listener. то я заканчиваю ListenThread(). также должен быть реализован метод TCP_Listener.Pending(), упомянутый здесь Proper way to stop TcpListener.

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