2012-04-04 5 views
1

У меня есть поток в функции, которая запускает прямой мониторинг, в основном открывает последовательный порт и непрерывно считывает данные из последовательного порта. Однако, если мне нужно прекратить этот поток, как мне это сделать? Потому что если я не завершу текущий поток, который открыл конкретный последовательный порт и считывал данные. Когда я закрою его и снова вызову функцию. Один и тот же последовательный порт не может быть открыт. Я подозреваю, что последовательный порт не закрыт должным образом и все еще работает в отдельном потоке. Поэтому я думаю, что я должен закончить этот поток, чтобы снова открыть тот же последовательный порт в следующий раз. Кто-нибудь знает, как этого добиться?Threading in winform - Compact .NET Framework 3.5

Я видел, что какой-то форум сказал, что Thread.Abort() опасен для использования. Его следует использовать только в крайнем случае.

Спасибо за помощь.

Чарльз

+0

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

ответ

2

Как правило, вы создаете метод, который запускается в фоновом потоке для прослушивания запросов на отмену. Это может быть так же просто, как логическое значение:

//this simply provides a synchronized reference wrapper for the Boolean, 
//and prevents trying to "un-cancel" 
public class ThreadStatus 
{ 
    private bool cancelled; 

    private object syncObj = new Object(); 

    public void Cancel() {lock(syncObj){cancelled = true;}} 

    public bool IsCancelPending{get{lock(syncObj){return cancelled;}}} 
} 

public void RunListener(object status) 
{ 
    var threadStatus = (ThreadStatus)status; 

    var listener = new SerialPort("COM1"); 

    listener.Open(); 

    //this will loop until we cancel it, the port closes, 
    //or DoSomethingWithData indicates we should get out 
    while(!status.IsCancelPending 
     && listener.IsOpen 
     && DoSomethingWithData(listener.ReadExisting()) 
     Thread.Yield(); //avoid burning the CPU when there isn't anything for this thread 

    listener.Dispose(); 
} 

... 

Thread backgroundThread = new Thread(RunListener); 
ThreadStatus status = new ThreadStatus(); 
backgroundThread.Start(status); 

... 

//when you need to get out... 
//signal the thread to stop looping 
status.Cancel(); 
//and block this thread until the background thread ends normally. 
backgroundThread.Join() 
2

Сначала кажется, у вас есть нить в ней и закройте все темы, Вы должны установить все из них фоновых потоков, прежде чем начать их, то они будут закрыты автоматически при выходе из приложения.

А потом попробуйте так:

Thread somethread = new Thread(...); 
someThread.IsBackground = true; 
someThread.Start(...); 

Приведи http://msdn.microsoft.com/en-us/library/aa457093.aspx

+0

+1 - Я бы добавил больше, если бы это было разрешено. Это самый простой способ. Это просто поток с последовательным портом, поэтому кто заботится, разрушает ли ОС его при выключении! ОС может легко справиться с циклами и/или заблокированными потоками, в отличие от кода пользователя. Свертывание с булевыми «стоп-флагами» или периодическая проверка состояний отмены лучше всего не делать вообще. Если поток не абсурдно нуждается в явном прекращении, не делайте этого! –

+0

Выполняет ли поток в этой форме автоматически, как только форма закрыта? –

+0

@ Charles-Да, он прекратит все потоки один раз, когда вы выйдете из приложения. – coder

1

Использовать логический флаг установить ложь первоначально и когда вы хотите, чтобы ваш поток бросить установить его так. По-видимому, ваш основной цикл потока должен контролировать этот флаг. Когда он увидит, что он изменился на истинный, а затем ваш опрос, закройте порт и выйдите из цикла основного потока.

Ваш главный цикл может выглядеть следующим образом:

OpenPort(); 
while (!_Quit) 
{ 
    ... check if some data arrived 
    if (!_Quit) 
    { 
     ... process data 
    } 
} 
ClosePort(); 

В зависимости от того, как ждать новых данных, которые вы можете использовать события (ManualResetEvent или AutoResetEvent) для того, чтобы разбудить свою нить, когда вы хотите его бросить.