2012-04-05 65 views
2

我有一個在c#(Visual Studio 2010)中開發的Windows應用程序,它與連接到PC的USB端口的USB-CAN轉換器進行交互。我在一個線程上實現了一個UI,在一個單獨的線程上實現了發送和接收邏輯。完成我的任務後,我想關閉此線程並返回到當前掛起的UI線程!C#多線程問題

我試圖用abort函數強制殺死線程,但它會拋出異常。那麼在完成我的任務後如何優雅地結束這個線程。

我有以下2個問題:

  1. 如何優雅地終止線程並返回到UI線程?
  2. 爲什麼這個傳輸和接收線程不會中止並掛起UI線程?

下面的代碼是供你參考:

#region recievedthrad 
public void ThreadProcReceive() 
{ 
    try 
    { 
     bool fDoExit = false; 

     do 
     { 
      if (bFlag) 
       DeleteAllResources(); // This will free all the driver resources. 

      // wait for receiving messages or exiting this thread 
      /* Note: After completion of the task, this method needs to return a 0 or 2 value. But still it returns 1 or 258 and never exits the thread. */ 

      int index = WaitHandle.WaitAny(m_RxWaitHandles); 
      if (index == 0) 
      { 
       // exit this thread 
       fDoExit = true; 
      } 
      else if (index == 1) 
      { 
       // receive all messages 
       ReceiveAllCanMessages(); 
      } 
      else if (index == 2) 
      { 
       // exit this thread 
       ReceiveStatus(UcanDotNET.USBcanServer.USBCAN_CHANNEL_CH0); 
      }  
     } while ((fDoExit == false)); 
    } 
    catch(Exception ex) 
    { 

    } 
} 
#endregion 
+2

我很困惑。你有GUI線程和其他線程做USB/CAN通信。爲什麼GUI線程掛起?如果掛起是因爲你試圖指示通信線程終止並等待它的句柄,(Thread.Join),那麼就不要這樣做!指出它完成,好吧,只是不要等待它。無論如何,你是否需要它 - 爲什麼不把它放在周圍呢? – 2012-04-05 11:56:13

+3

這可能是一個使用BackgroundWorker的好地方 – 2012-04-05 11:59:54

+2

在'index == 2'的情況下,你有一個註釋'//退出這個線程'但是你沒有設置'fDoExit = true'。 – Henrik 2012-04-05 12:19:29

回答

0

如何優雅地終止線程並返回到UI線程?

如果線程被阻塞裏面的這些UcanDotNet要求,那麼你將不得不使用另一個UcanDotNet API進行解鎖一個......假設這個庫已經可以正常終止其業務之一的能力。我不熟悉這個UcanDotNet庫,所以我不知道它的功能是什麼。

如果像大多數第三方庫一樣,這個UcanDotNet庫沒有提供取消操作的必要手段,那麼你真的別無選擇,只能將所有這些調用放到另一個進程中,並通過WCF與它通信。這樣,如果你不得不突然終止它,那麼你只需要終止進程。殺死另一個進程比反覆調用Thread.Abort更安全,因爲中止線程會損壞內存。

爲什麼這個傳輸和接收線程不會中止並掛起 的UI線程?

Thread.Abort是一個阻塞呼叫。它等待中止被注入到線程中。我懷疑你的問題是線程運行的環境不允許異步異常注入,例如finally塊或非託管代碼。使用下面的代碼很容易證明這一點。

public static void Main(string[] args) 
{ 
    int i = 0; 
    var t = new Thread(() => 
    { 
     try 
     { 
     } 
     finally 
     { 
      while (true) i++; 
     } 
    }); 
    t.Start(); 
    Thread.Sleep(1000); 
    t.Abort(); // this blocks indefinitely! 
    Console.WriteLine("aborted"); // never gets here! 
}