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

Posted

技术标签:

【中文标题】在所有情况下都必须调用 EndRead() 吗?【英文标题】:Must call EndRead() in ALL cases? 【发布时间】:2011-06-17 20:12:20 【问题描述】:

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

即使对于 EndRead() 将引发异常的情况也是如此,例如在发出 BeginRead() 后 NetworkStream 已关闭的情况?

我不希望抛出异常的开销,但也不希望泄露 BeginRead() 保留的操作系统宝贵资源。

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

我做错了吗?

谢谢!

【问题讨论】:

您在处理异常时实际看到了什么样的性能影响? 我无法检测到。但是我已经阅读并相信这是真的,虽然将代码放在 try-catch 块中对性能的影响最小,但实际上抛出异常(需要捕获)在计算上是昂贵的。建议(在某处)不应使用异常来传达正常操作的结果——提前检查成功标准可以避免或至少减少异常。例外只应在例外情况下使用,而不是不可避免的情况。 .Net 框架和其他库中有很多地方捕获异常是唯一的方法。此外,由于套接字的状态可能在检查成功标准和执行后续调用之间发生变化(无论这种可能性多么小),仍然可能导致异常。但是如果可以避免的话,我想知道最合适的用法。 正如 Anton(另一位)建议的那样,“最合适的”是调用 EndRead。如果捕获异常会给您带来实际 问题,那么您可能需要重新考虑一些事情,可能是您选择的编程语言:P 正如您所说,在框架中没有摆脱异常。但我认为您尝试优化得太早了。 【参考方案1】:

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

注意:这些是使用 Reflector 获得的实现细节。警告购买者。

【讨论】:

不能说真的,因为我对您的应用一无所知,但我建议您致电 EndRead,除非您分析您的应用并发现异常 EndRead throws 会导致显着的性能损失。

以上是关于在所有情况下都必须调用 EndRead() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

LayoutAnimation 在任何情况下都可以工作吗?

将我的库迁移到64位时,我是否必须更改param的类型?

Delphi XE3 - Reuse socket rsTrue 在任何情况下都会被系统覆盖吗?

YouTube 缩略图链接并非在所有情况下都有效

子类都会首先调用父类的构造函数吗?

Laravel 搜索查询在所有情况下都不会得到结果,即使它应该