使用AsyncEnumerator实现APM模式时的异常处理

编程入门 行业动态 更新时间:2024-10-25 16:27:25
本文介绍了使用AsyncEnumerator实现APM模式时的异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试使用Richter的 AsyncEnumerator 类实现APM模式.目标是实现一个 ExtendedSocket 类,该类派生自 Socket ,并提供 Begin/EndReceiveFixed 和 Begin/EndSendFixed 异步发送或接收固定字节数的方法.

I'm trying to implement the APM pattern using Richter's AsyncEnumerator class. The goal is to implement an ExtendedSocket class which is derived from Socket and offers Begin/EndReceiveFixed and Begin/EndSendFixed methods to send or receive a fixed amount of bytes asynchronously.

代码看起来像这样(我省略了发送部分,因为它与接收部分基本相同)

The code looks like this (I omitted the sending part since it is basically the same as for receiving):

class ExtendedSocket : Socket { public ExtendedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) : base(addressFamily, socketType, protocolType) { } public IAsyncResult BeginReceiveFixed(byte[] buffer, SocketFlags socketFlags, AsyncCallback callback, Object state) { AsyncEnumerator ae = new AsyncEnumerator(); return ae.BeginExecute(DoReceiveFixed(ae, buffer, socketFlags), callback, state); } public void EndReceiveFixed(IAsyncResult asyncResult) { AsyncResult ar = asyncResult as AsyncResult; (ar.InitiatingObject as AsyncEnumerator).EndExecute(ar); } private IEnumerator<Int32> DoReceiveFixed(AsyncEnumerator ae, byte[] buffer, SocketFlags socketFlags) { int totalReceivedBytes = 0; while (totalReceivedBytes < buffer.Length) { BeginReceive(buffer, totalReceivedBytes, buffer.Length - totalReceivedBytes, socketFlags, ae.End(), null); yield return 1; totalReceivedBytes += EndReceive(ae.DequeueAsyncResult()); } } }

这在我的应用程序中工作得很好,但是我不知道如何在 DoReceiveFixed 中处理异常.我想实现默认的APM行为,其中在调用 EndReceiveFixed 时抛出(重新)异常.

This works perfectly fine in my application but I don't know how to handle exceptions in DoReceiveFixed. I'd like to implement the default APM behaviour where exceptions are (re)thrown when EndReceiveFixed is called.

不幸的是,我无法访问 DoReceiveFixed 中的 AsyncResult 对象,因此我无法调用 SetAsCompleted 上的异常 AsyncResult 对象.

Unfortunately I don't have access to the AsyncResult object inside DoReceiveFixed, so I can't call SetAsCompleted with an exception on the AsyncResult object.

我当前的解决方法是使用 AsyncEnumerator< Exception> 而不是 AsyncEnumerator 这样:

My current workaround is to use AsyncEnumerator<Exception> instead of AsyncEnumerator like this:

class ExtendedSocket : Socket { public ExtendedSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) : base(addressFamily, socketType, protocolType) { } public IAsyncResult BeginReceiveFixed(byte[] buffer, SocketFlags socketFlags, AsyncCallback callback, Object state) { AsyncEnumerator<Exception> ae = new AsyncEnumerator<Exception>(); return ae.BeginExecute(DoReceiveFixed(ae, buffer, socketFlags), callback, state); } public void EndReceiveFixed(IAsyncResult asyncResult) { AsyncResult ar = asyncResult as AsyncResult; AsyncEnumerator<Exception> ae = ar.InitiatingObject as AsyncEnumerator<Exception>; ae.EndExecute(ar); if (ae.Result != null) { throw ae.Result; } } private IEnumerator<Int32> DoReceiveFixed(AsyncEnumerator<Exception> ae, byte[] buffer, SocketFlags socketFlags) { int totalReceivedBytes = 0; Exception catchedException = null; while (totalReceivedBytes < buffer.Length) { try { BeginReceive(buffer, totalReceivedBytes, buffer.Length - totalReceivedBytes, socketFlags, ae.End(), null); } catch (Exception ex) { catchedException = ex; break; } yield return 1; try { totalReceivedBytes += EndReceive(ae.DequeueAsyncResult()); } catch (Exception ex) { catchedException = ex; break; } } ae.Result = catchedException; } }

这似乎可行,但我不太喜欢这种解决方案.有一个更好的方法吗?也许有一种方法可以从 DoFixedReceive 内部访问 AsyncResult 对象?

This seems to work but I don't really like this solution. Is there a better way to do this? Maybe there is a way to get access to the AsyncResult object from inside DoFixedReceive?

推荐答案

在杰弗里·里希特(Jeffrey Richter)的帮助下,我解决了我的问题(请参阅此处):

With the help of Jeffrey Richter I solved my problem (see here):

没有必要在迭代器中捕获所有异常并手动将其重新抛出. AsyncEnumerator 为我们做到了.

There is no need to catch all exceptions in an iterator and rethrow them manually. AsyncEnumerator does this for us.

但是请注意您的调试器设置.我需要在常规调试页面上取消选中仅启用我的代码"设置.否则,如果迭代器内部发生异常,调试器会在 AsyncEnumerator 有机会捕获异常之前,以未处理的异常消息中断.

But be careful with your debugger settings. I needed to uncheck the 'Enable Just My Code' setting on the general debugging page. Otherwise, if an exception occurs inside the iterator, the debugger breaks with an unhandled exception message before AsyncEnumerator has the chance to catch the exception.

更多推荐

使用AsyncEnumerator实现APM模式时的异常处理

本文发布于:2023-11-09 20:21:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1573337.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:异常   模式   AsyncEnumerator   APM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!