2012-04-05 77 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! 
}