Safe handle has been closed异常的原因及解决思路

简介: Exception: 2013-05-30 19:28:26,750 [3] ERROR Topshelf.Runtime.Windows.WindowsServiceHost Error 0- The service threw an unhandled exception System.

Exception:

2013-05-30 19:28:26,750 [3] ERROR Topshelf.Runtime.Windows.WindowsServiceHost Error 0- The service threw an unhandled exception
System.ObjectDisposedException: Safe handle has been closed
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
   at Microsoft.Win32.Win32Native.SetEvent(SafeWaitHandle handle)
   at System.Threading.EventWaitHandle.Set()
   at System.IO.Ports.SerialStream.AsyncFSCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

异常原因及解决思路:
一:
The message says that you are trying to access an object which is already disposed.

Check and see your objects are handling well the 'Dispose' and 'Class Destruction'
PokeIn disposes client's objects when the client is disconnected. But this operation is Thread and Exception safe.
http://pokein.com/Discussions/tabid/62/forumid/4/postid/1069/scope/posts/Default.aspx

二:
You are disposing something which is still being used by a different thread.
http://stackoverflow.com/questions/4473216/diagnose-objectdisposedexception-safe-handle-has-been-closed
三:

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:

  • 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.

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();

}

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.

What would be the proper way to close my thread. The Stop()/Start() are used for when I reconfigure the port.

There are a few ways you could do it and I've given an example using a ManualResetEvent which is a pretty common mechanism..

You're welcome.. I hope you understand why Thread.Abort is not good practice. If you would like to find out more on the subject - there is a really great book about concurrency in Windows by Joe Duffy: bluebytesoftware.com/books/winconc/winconc_book_resources.html

I've found that unplugging USB-based serial ports when they're open tends to cause weird behaviors including "safe handle has been closed" exceptions. For devices which are supposed to operate as long as they're plugged in, but which may be unplugged at any time, the only remedy I've found to work consistently is to spawn a separate application to handle each device, and use some sort of pipe to bind such applications to the main app. Really horribly hokey, but I don't know what else to do.

http://stackoverflow.com/questions/1319003/safe-handle-has-been-closed-with-serialport-and-a-thread-in-c-sharp

相关文章
|
Web App开发 前端开发
【前端异常】Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
【前端异常】Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
712 0
|
4月前
|
弹性计算 监控 Serverless
函数计算操作报错合集之调用不成功,报错:Function instance health check failed on port 9000 in 120.7 seconds.该怎么办
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
|
3月前
|
Serverless 应用服务中间件 网络安全
函数计算操作报错合集之如何处理报错 "Function instance health check failed on port 7860 in 120 seconds."
在使用函数计算服务(如阿里云函数计算)时,用户可能会遇到多种错误场景。以下是一些常见的操作报错及其可能的原因和解决方法,包括但不限于:1. 函数部署失败、2. 函数执行超时、3. 资源不足错误、4. 权限与访问错误、5. 依赖问题、6. 网络配置错误、7. 触发器配置错误、8. 日志与监控问题。
|
4月前
|
缓存
Error: EIO: i/o error, read如何解决
Error: EIO: i/o error, read如何解决
|
5月前
|
API Android开发 开发者
debug常见错误,出现debug时出现跑进为条件为false的if语句,DELETE_FAILED_INTERNAL_ERROR Error while In
debug常见错误,出现debug时出现跑进为条件为false的if语句,DELETE_FAILED_INTERNAL_ERROR Error while In
37 5
飞思卡尔codewarrior下载出现USBD connection error:Failed to connect to targe(Reason :Target reset pin time out)
飞思卡尔codewarrior下载出现USBD connection error:Failed to connect to targe(Reason :Target reset pin time out)
飞思卡尔codewarrior下载出现USBD connection error:Failed to connect to targe(Reason :Target reset pin time out)
|
数据库 NoSQL MongoDB
Mongodb中经常出现的错误(汇总)child process failed, exited with error number
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 异常处理汇总-数据库系列  http://www.cnblogs.com/dunitian/p/4522990.
1431 0
|
测试技术 数据库 关系型数据库
ORA-03113: end-of-file on communication channel 解决思路&方法
场景:测试数据库的hang住问题。 长期解决的方法:定时做rman备份,删除归档日志 1.把数据库启动至mount状态 SQL> startup mount ORACLE instance started.
2535 0
|
安全 Java 容器
简述快速失败(fail-fast)和安全失败(fail-safe)?
快速失败(fail-fast)和安全失败(fail-safe)
177 0