C#多线程问题

C#多线程问题,c#,winforms,multithreading,C#,Winforms,Multithreading,我有一个在c#(Visual Studio 2010)中开发的windows应用程序,它与连接到PC USB端口的USB-CAN转换器交互。我在一个线程上实现了UI,在另一个线程上实现了传输和接收逻辑。完成任务后,我想关闭此线程并返回当前挂起的UI线程 我试图使用abort函数强制终止线程,但它抛出了一个异常。那么,如何在完成任务后优雅地结束这个线程呢 我有以下两个问题: 如何优雅地终止线程并返回UI线程 为什么这个传输和接收线程没有中止和挂起UI线程 以下代码供您参考: #region rec

我有一个在c#(Visual Studio 2010)中开发的windows应用程序,它与连接到PC USB端口的USB-CAN转换器交互。我在一个线程上实现了UI,在另一个线程上实现了传输和接收逻辑。完成任务后,我想关闭此线程并返回当前挂起的UI线程

我试图使用abort函数强制终止线程,但它抛出了一个异常。那么,如何在完成任务后优雅地结束这个线程呢

我有以下两个问题:

  • 如何优雅地终止线程并返回UI线程
  • 为什么这个传输和接收线程没有中止和挂起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
    
    如何优雅地终止线程并返回UI线程

    如果线程在其中一个UcanDotNet调用中阻塞,则必须使用另一个UcanDotNet API来解除阻塞…假设此库能够正常终止其一个操作。我不熟悉这个UcanDotNet库,所以我不知道它的功能是什么

    如果像大多数第三库一样,这个UcanDotNet库没有提供取消操作的必要手段,那么您真的没有其他选择,只能将所有这些调用放在另一个进程中,并通过WCF与之通信。这样,若您必须突然终止它,那个么您只需终止进程。终止另一个进程比调用
    线程更安全。无论如何,中止
    ,因为中止线程会损坏内存

    为什么这个传输和接收线程没有中止和挂起 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!
    }
    
    如何优雅地终止线程并返回UI线程

    如果线程在其中一个UcanDotNet调用中阻塞,则必须使用另一个UcanDotNet API来解除阻塞…假设此库能够正常终止其一个操作。我不熟悉这个UcanDotNet库,所以我不知道它的功能是什么

    如果像大多数第三库一样,这个UcanDotNet库没有提供取消操作的必要手段,那么您真的没有其他选择,只能将所有这些调用放在另一个进程中,并通过WCF与之通信。这样,若您必须突然终止它,那个么您只需终止进程。终止另一个进程比调用
    线程更安全。无论如何,中止
    ,因为中止线程会损坏内存

    为什么这个传输和接收线程没有中止和挂起 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!
    }
    

    我很困惑。您有GUI线程和其他线程执行USB/CAN通信。为什么GUI线程挂起?如果它挂起是因为您试图向comms线程发送终止信号并等待其句柄(thread.Join),那么就不要这样做!发信号让它结束,好吧,别再等了。不管怎样,你需要它来完成吗?为什么不把它放在一边呢?这可能是一个使用BackgroundWorker的好地方,在这种情况下
    index==2
    你有一个注释
    //退出这个线程
    ,但你没有设置
    fDoExit=true
    。我很困惑。您有GUI线程和其他线程执行USB/CAN通信。为什么GUI线程挂起?如果它挂起是因为您试图向comms线程发送终止信号并等待其句柄(thread.Join),那么就不要这样做!发信号让它结束,好吧,别再等了。你需要它来完成吗?为什么不把它放在一边呢?这可能是一个使用BackgroundWorker的好地方,在这种情况下
    index==2
    你有一个注释
    //退出这个线程
    ,但你没有设置
    fDoExit=true