在所有情况下都必须调用EndRead()吗?

7

关于使用(双向)NetworkStream的异步IO,MSDN表示“对于每次调用BeginRead,必须调用一次EndRead。”

即使在EndRead()会抛出异常的情况下,例如在发出BeginRead()后关闭了NetworkStream,这也是正确的吗?

我不想有异常抛出的开销,但也不想泄漏由BeginRead()保留的操作系统宝贵资源。

我还知道,在测试流状态和条件EndRead()之间,流可能会被关闭,但是如果我们知道流已关闭,则可以省略EndRead(),这将节省大多数情况下的异常处理。

我做错了吗?

谢谢!


当您处理异常时,实际上会看到什么样的性能影响? - anton.burger
我没有发现任何问题。但是我已经阅读并相信这是真实的,尽管将代码放在try-catch块中对性能影响很小,但实际上抛出异常(需要捕获)是计算开销大的。建议(某处)不应使用异常来传达正常操作的结果 - 提前检查成功标准可以避免或至少减少异常。异常只应在非常规情况下使用,而不是必然情况下使用。 - Jason Kleban
在 .Net 框架和其他库中,有很多地方只能通过捕获异常来处理。此外,由于套接字的状态可能会在检查成功条件和执行后续调用之间发生变化(尽管这种情况可能很少见),仍然可能导致异常。但是如果可以避免,我想知道最适当的用法。 - Jason Kleban
1
正如Anton(另一个人)所建议的那样,“最合适”的方法是调用EndRead。如果捕获异常会导致实际问题,那么您可能需要重新考虑一些事情,可能是您选择的编程语言:P就像您所说的那样,在框架中无法避免异常。但我认为您正在尝试过早优化。 - anton.burger
1个回答

7
您好,以下是您需要翻译的内容:

GCHandle会固定您的缓冲区和其他一些非托管资源,并在完成端口回调时释放。非托管的OVERLAPPED结构将一直存在,直到IAsyncResult被终止。如果您的应用程序中的网络负载不大,则这可能是可以容忍的,但如果您的应用程序每秒处理许多连接,则可能会成为问题,因为终止仅发生在完整的GC收集之后并且在单独的线程上。

NB:这些是使用Reflector获取的实现细节。买家自负。


3
我无法确切地说我对你的应用一无所知,但我建议你调用 EndRead,除非你对你的应用程序进行了性能分析并发现 EndRead 抛出的异常会导致显著的性能损失。 - Anton Tykhyy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接