gpt4 book ai didi

c# - 如何终止挂起的 APM 操作

转载 作者:太空宇宙 更新时间:2023-11-03 11:56:10 25 4
gpt4 key购买 nike

如果你有一个挂起的操作,例如

stream.BeginRead(_buffer, 0, _buffer.Length, _asyncCallbackRead, this);

然后您关闭流提供程序,例如

serialPort.Close();

你不出所料地引发了异常。

是否有一种首选方法可以在关闭端口之前取消挂起的 APM 操作?


Colby 的回答不是我所希望的答案,但他至少切断了一条毫无结果的询问之路。

很高兴我找到了解决方案。

对于每个流,我在类 DeviceSession 中维护各种状态信息。此类有一个方法 ReadStream 为处理传入数据的 AsyncCallback 提供实现。

请注意,_asyncCallbackRead 和所有其他以下划线开头的变量都是在 DeviceSession 的构造函数中分配的类私有(private)成员。

构造函数还提供了对 _stream.BeginRead 的初始调用。

void ReadStream(IAsyncResult ar)
{
if (IsOpen)
try
{
DevicePacket packet;
int cbRead = _stream.EndRead(ar);
_endOfValidData += cbRead;
while ((packet = GetPacket()) != null)
CommandStrategy.Process(this, packet);
_stream.BeginRead(_buffer, _endOfValidData,
_buffer.Length - _endOfValidData,
_asyncCallbackRead, null);
}
catch (Exception ex)
{
Trace.TraceError("{0}\r\n{1}", ex.Message, ex.StackTrace);
_restart(_streamProvider, _deviceId);
}
}

请注意,我没有设置 ar.AsyncState。因为回调委托(delegate)引用 DeviceSession 的特定实例的方法,所以详细且强类型的上下文信息(包含在 DeviceSession 的此实例的成员中)自动在范围内。这就是拥有 session 对象的意义所在。

回到中止监听器的主题,关闭流提供程序会触发回调,但尝试调用 EndRead 会导致 IOException

通常这样的异常表示需要重新启动监听器的故障,并且需要通过重新启动流提供程序并重新创建 session 来响应。由于缺乏可靠的独立于流提供者的方法来确定提供者是否出现故障或用户是否正在尝试重新启动连接(例如,将新设备插入端口),这变得复杂。

诀窍是在DeviceSession中添加更多上下文(IsOpen)来指示 session 是打开还是已经关闭,并使用它来顺利完成最终ReadStream 的中止执行。

如果 IsOpentrue,则 IOException 表示需要恢复的故障。如果 IsOpenfalse,则失败是故意引起的,无需采取任何措施。

最佳答案

[受到 Richter 的 CLR 中关于 APM 的章节的启发,我决定看看 SO 在这个主题上有什么好东西,我发现了这个问题。我认为 Peter 在这里提出了一个很好的问题并做了一些研究——这就是结果]

Jeffrey Richter in CLR via C#(第 27 章)讨论了他的 AsyncEnumerator 类,该类(据说)可以减轻 APM 编程的大部分痛苦。此类的功能之一(他的免费 Power Threading Libary 的一部分)是取消异步操作的能力。

可以从上面的链接下载该类。该页面还包含指向 Yahoo Group Richter 的链接,该链接旨在为该库提供有限的支持。

他在这些 MSDN 文章中介绍了该库:

Simplified APM With The AsyncEnumerator
More AsyncEnumerator Features

关于c# - 如何终止挂起的 APM 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/385381/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com