我有一个C#程序,它使用的是与串口设备通信 内置在SeralPort类中。但是,我想做异步写入 为此我使用BaseStream.BeginWrite()。在异步回调中 我调用BaseStream.EndWrite()。这一切都很好。但是,偶尔 我想在BeginWrite()完成但是调用之前关闭一个端口 只要BeginWrite()处于挂起状态,Close()会使其挂起。 我试过调用EndWrite()但是如果BeginWrite()也会挂起 等待中。如何杀死BeginWrite()线程?似乎有 不是BaseStream.Abort()或类似的。
由于
答案 0 :(得分:1)
我找到了一种方法,但它有点hackish。此方法关闭端口并中止,但在此过程中抛出了几个异常。基本上,我使用反射来获取设备的文件句柄,如下所示:
object p = _port.BaseStream.GetType().GetField("_handle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField).GetValue(_port.BaseStream);
IntPtr hFile = (IntPtr)p.GetType().GetField("handle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField).GetValue(p);
其中 _port 是打开的SerialPort。然后关闭文件如下
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr hFile);
CloseHandle(hFile);
通过调用BaseStream中的一个私有方法可能有更好的方法,但这是一种方式:)
答案 1 :(得分:0)
我还认为如果Stream.Close()
不能解决问题,则无法取消操作。 EndWrite()
按设计阻塞,同一线程上的BeginWrite()
和EndWrite()
序列与调用同步函数相同。
实际上,甚至没有一个线程可以运行。该操作可能在内部使用IO完成端口,并且仅在线程池线程上触发回调。 (自从我调查那些东西已经有一段时间了)
但你可以做的是'放弃'流,在你的代码中设置一个标志,当回调到来时,如果设置了标志,就关闭流。请务必在旗帜周围放置lock
或将其设为volatile