使用 BaseStream 强制终止串行 COM 端口 IO 应用程序中的 BeginWrite

发布于 2024-07-27 03:50:31 字数 363 浏览 4 评论 0原文

我有一个 C# 程序,它使用以下命令与串行设备进行通信 内置 SeralPort 类。 但是,我想做异步写入 为此,我正在使用 BaseStream.BeginWrite()。 在异步回调中 我调用 BaseStream.EndWrite()。 这一切都运行良好。 然而,有时 我想在 BeginWrite() 完成之前关闭端口,但调用 只要 BeginWrite() 处于挂起状态,Close() 就会使其挂起。 我尝试过调用 EndWrite() 但如果 BeginWrite() 也会挂起 等待中。 如何终止 BeginWrite() 线程? 似乎有 不是 BaseStream.Abort() 或类似的。

谢谢

I have a C# program that communicates with serial devices using the
built in SeralPort class. However, I want to do asynchronous writes
and for that I am using BaseStream.BeginWrite(). In the async callback
I call BaseStream.EndWrite(). All this works fine. However, on occasion
I want to close a port BEFORE the BeginWrite() has finished but calling
Close() causes it to hang as long as BeginWrite() is pending.
I have tried calling EndWrite() but that also hangs if BeginWrite()
is pending. How do I kill the BeginWrite() thread? There appears to
be no BaseStream.Abort() or similar.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一腔孤↑勇 2024-08-03 03:50:31

我找到了一种方法,但有点黑客。 此方法关闭端口并中止,但在此过程中引发几个异常。 基本上,我使用反射来获取设备的文件句柄,如下所示:

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 是打开的串行端口。 然后我按如下方式关闭文件

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr hFile);
CloseHandle(hFile);

可能有更好的方法通过调用 BaseStream 中的私有方法之一,但这是一种方法:)


I have a found a way but it is a bit hackish. This method closes the port and aborts but throws a couple of exceptions in the process. Basically, I use reflection to get the device's file handle as follows:

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

Where _port is the opened SerialPort. I then close the file as follows

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr hFile);
CloseHandle(hFile);

Probably there is a better way by calling one of the private methods in BaseStream but this is one way :)


旧竹 2024-08-03 03:50:31

我还认为,如果 Stream.Close() 不起作用,您就无法取消操作。 EndWrite() 按设计阻塞,同一线程上的 BeginWrite()EndWrite() 序列与调用同步函数相同。

实际上,有可能甚至没有线程在运行您的操作。 该操作可能在内部使用 IO 完成端口,并且仅在线程池线程上触发回调。 (自从我研究这些东西以来已经有一段时间了)

但是你可以做的是“放弃”流,在代码中设置一个标志,当回调到达时,如果设置了标志,只需关闭流。 请记住在标志周围放置或使其易失性

I also think that you can't cancel the operation if Stream.Close() doesn't do the trick. EndWrite() blocks by design, a sequence of BeginWrite() and EndWrite() on the same thread is identical to calling the synchronous function.

Actually, it's possible that there's not even a thread running for your operation. The operation might use IO completion ports internally and only fire the callback on a threadpool thread. (it's been some time since I looked into that stuff)

But what you can do is 'abandon' the stream, set a flag in your code and when the callback arrives, just close the stream if the flag is set. Remember to put a lock around the flag or make it volatile

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文