"安全手柄已经关闭"用的SerialPort和C#线程 [英] "Safe handle has been closed" with SerialPort and a thread in C#

查看:345
本文介绍了"安全手柄已经关闭"用的SerialPort和C#线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

,大家下午好!

我有这个线程的SerialPort 包装,从串口在一条线上读取。这是我的线程的代码

I have this threaded SerialPort wrapper that reads in a line from the serial port. Here is my thread's code.

protected void ReadData()
{
     SerialPort serialPort = null;
     try
     {
         serialPort = SetupSerialPort(_serialPortSettings);
         serialPort.Open();

         string data;
         while (serialPort.IsOpen)
         {
             try
             {

                 data = serialPort.ReadLine();
                 if (data.Length > 0)
                     ReceivedData(serialPort, new ReceivedDataEventArgs(data));

             }
             catch (TimeoutException)
             {
                 //  No action
             }
         }
     }
     catch (ThreadAbortException)
     {
         if (serialPort != null)
             serialPort.Close();
     }
}

当我打电话 MyThread的。中止(); 我得到一个异常(不带线或引用代码)安全处理已经关闭。任何人都可以发现什么,我做错了什么?谢谢你。

when I call myThread.Abort(); I get an exception (with no line or reference to code) "Safe handle has been closed". Can anyone spot what I am doing wrong? Thanks.

顺便说一句,我有一个开始()停止( )创建线程并中止线程,恭恭敬敬。

By the way, I have a Start() and a Stop() that creates the thread and aborts the thread, respectfully.

推荐答案

我会怀疑,这是因为你使用Thread.Abort的结束线程 - 这通常是令人难以接受的。该线程的行为,当你的中止的它是不可预测的。正因为如此,既然串口是包装过的本地代码,也有本地的资源 - 通过在SafeHandle的代表.NET - 这出人意料地得到处置的,所以你得到的异常。

I would suspect that it is because you are using Thread.Abort to end the thread - which is generally frowned upon. The thread behavior when you abort it is not predictable. Because of that, since the serial port is a wrapper over native code, there are native resources - represented by a SafeHandle in .NET - which get disposed of unexpectedly and so you get the Exception.

您可以想想你的线程是这样发生的:

You can think about what happens with your thread like this:


  • 您启动你的线程

  • 您打开串口(分配本土资源和使用的SafeHandle(S)举行对这些资源)

  • 您启动从串口读

  • 然后在某个点(不期而至您的线程)调用Thread.Abort的就可以了

  • 极有可能在你的代码线程是在这一点上试图访问串行端口(读取数据)

  • 的线程被打死,串口句柄隐含地摧毁

  • 你从串行端口的ReadLine()函数中的代码抛出一个异常,因为它有句柄不再有效

  • you start your thread
  • you open the serial port (which allocates native resources and uses SafeHandle(s) to hold on to those resources)
  • you start reading from the serial port
  • then at some point (unexpected to your thread) you call Thread.Abort on it
  • most likely the code in your thread is at that point trying to access the serial port (to read data)
  • the thread gets killed and the serial port handle is destroyed implicitly
  • you get an exception thrown from the code inside the ReadLine() function of the serial port because the handle it had is no longer valid

你真的应该使用中止线程,让你得到一个合适的机会接近和串行端口的配置不同的方法。

You really should use a different method for aborting the thread so that you get a proper chance to close and dispose of the serial port.

一个适当的方式来关闭线程可以使用的ManualResetEvent这样实现:

A proper way to close your thread could be implemented using a ManualResetEvent like this:

protected ManualResetEvent threadStop = new ManualResetEvent(false);

protected void ReadData()
{
     SerialPort serialPort = null;
     try
     {
         serialPort = SetupSerialPort(_serialPortSettings);
         serialPort.Open();

         string data;
         while (serialPort.IsOpen)
         {
             try
             {

                 data = serialPort.ReadLine();
                 if (data.Length > 0)
                     ReceivedData(serialPort, new ReceivedDataEventArgs(data));

             }
             catch (TimeoutException)
             {
                 //  No action
             }

             // WaitOne(0) tests whether the event was set and returns TRUE
             //   if it was set and FALSE otherwise.
             // The 0 tells the manual reset event to only check if it was set
             //   and return immediately, otherwise if the number is greater than
             //   0 it will wait for that many milliseconds for the event to be set
             //   and only then return - effectively blocking your thread for that
             //   period of time
             if (threadStop.WaitOne(0))
                 break;
         }
     }
     catch (Exception exc)
     {
         // you can do something here in case of an exception
         // but a ThreadAbortedException should't be thrown any more if you
         // stop using Thread.Abort and rely on the ManualResetEvent instead
     }
     finally
     {
         if (serialPort != null)
             serialPort.Close();
     }
}

protected void Stop()
{
    // Set the manual reset event to a "signaled" state --> will cause the
    //   WaitOne function to return TRUE
    threadStop.Set();
} 



当然,使用事件的方法来阻止你有线程<当STRONG>的要小心包括你所有的长时间运行的循环或任务的。如果你没有你的线程可能会出现不回应你的设置事件 - 直到它得到了长时间运行的循环,或者任务,并得到一个机会,以看到该事件已设置

Of course, when using the events method to stop the thread you have to be careful to include an event state check in all your long running loops or tasks. If you don't your thread may appear not to respond to your setting the event - until it gets out of the long-running loop, or task and gets a chance to "see" that the event has been set.

这篇关于&QUOT;安全手柄已经关闭&QUOT;用的SerialPort和C#线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆