C#-异步回调中的异常传播问题
下面的代码非常简单,我的问题非常简单:C#-异步回调中的异常传播问题,c#,.net,C#,.net,下面的代码非常简单,我的问题非常简单: 为什么AsyncCallback方法“HandleConnection”没有向“Connect”方法传播异常,以及如何传播异常 1-我想这是很正常的行为。但我希望能全面解释为什么会发生这种情况,以及发动机罩后面到底发生了什么 2-是否有任何(快速且简单)的方法通过我的应用程序传播异常 预先警告我知道这里的很多人都很挑剔,我期待有人会说“你为什么不直接把ManageException放在“HandleConnect”方法中呢?长话短说,我们就说“我有我的理
为什么AsyncCallback方法“HandleConnection”没有向“Connect”方法传播异常,以及如何传播异常
1-我想这是很正常的行为。但我希望能全面解释为什么会发生这种情况,以及发动机罩后面到底发生了什么
2-是否有任何(快速且简单)的方法通过我的应用程序传播异常 预先警告我知道这里的很多人都很挑剔,我期待有人会说“你为什么不直接把ManageException放在“HandleConnect”方法中呢?长话短说,我们就说“我有我的理由了”“哈哈,我刚刚在这里发布了一个代码示例,我想以更进一步的方式传播这个异常,并做比“N-upper”代码中其他地方显示的更多的事情 编辑
作为对评论的回答,我之前也尝试过这一点,但没有运气:
private void HandleConnect(IAsyncResult ar)
{
try
{
ipcState.IpcSocket.EndConnect(ar);
}
catch(Exception x)
{
throw x; // Exception Blows here. It is NOT propagated.
}
}
我的解决方案:
最后,我放置了一个事件处理程序,每个相关的代码逻辑都订阅它。这样,异常不仅会被吞没,也不会被吹走,而是会被广播一个通知
public event EventHandler<MyEventArgs> EventDispatch;
private void HandleConnect(IAsyncResult ar)
{
try
{
ipcState.IpcSocket.EndConnect(ar);
}
catch(Exception x)
{
if (EventDispatch!= null)
{
EventDispatch(this, args);
}
}
}
//Priorly, I push subscriptions like that :
tcpConnector.EventDispatch += tcpConnector_EventDispatch;
public void tcpConnector_EventDispatch(object sender, VfxTcpConnectorEventArgs args)
{
//Notify third parties, manage exception, etc.
}
public EventHandler EventDispatch;
专用void HandleConnect(IAsyncResult ar)
{
尝试
{
ipcState.IpcSocket.EndConnect(ar);
}
捕获(异常x)
{
if(EventDispatch!=null)
{
事件调度(本,args);
}
}
}
//首先,我会这样推送订阅:
tcpConnector.EventDispatch+=tcpConnector\u EventDispatch;
public void tcpConnector_EventDispatch(对象发送方,VfxTcpConnectorEventArgs参数)
{
//通知第三方、管理例外情况等。
}
这有点不正确,但是当您使用
BeginConnect
异步连接时,它可以正常工作。您将获得以下事件链:
Connect
通过BeginConnect
发布连接请求Connect
方法返回HandleConnect
由框架使用连接的结果调用Connect
已返回,因此try-catch块不再处于活动状态。这是使用异步实现时的行为
在Connect
中捕获异常的唯一原因是BeginConnect
无法启动后台连接任务。例如,如果BeginConnect
在启动后台操作之前验证提供的参数,并在参数不正确时引发异常,则可能出现这种情况
您可以使用事件在中心位置捕获任何未处理的异常。一旦异常达到该级别,可能很难实现任何形式的恢复,因为异常可能来自任何地方。如果您有一个恢复方法-捕获尽可能靠近原点的异常。如果您只记录/通知用户-在一个地方集中捕获通常会更好。进一步了解Anders所指出的,阅读以下内容可能是一个好主意: 并研究如何使用类似AsyncCallback的方法将回调方法传递到对BeginConnect的异步调用(如果确实存在)中,您可以在try-catch块中检索委托并调用EndInvoke 例如:
一种选择是对现有代码使用AsyncWaitHandle 为了更好地处理异常,您必须使用基于事件的编程模型,或者修改代码以使用BackgroundWorker组件,该组件支持从工作线程向主线程报告错误 以下链接提供了一些关于此主题的讨论和文章:
MSDN示例:仅传播未处理的异常。如果它被抓住了,它就会被处理。您需要类似于
throw x
的东西来强制它在一个级别捕获和处理它之后继续传播。@mellamokb:但是应该在哪里处理抛出的异常呢?方法HandleConnection正在另一个线程上运行。没有“传播”,也没有将异常传播到的代码。您的Connect()方法很久以前就停止运行了。如果要阻止程序终止,则需要处理异常。Swallow ObjectDisposedException,在主程序关闭套接字时引发。任何其他操作都会使您的程序处于“连接不可用”状态。谢谢。完美的这正是我所怀疑的。但我需要一个彻底而有力的确认。第二点呢?:-)@MikaJacobi仅适用于不使用异步方法的情况,因为如果要传播,主应用程序/线程必须等待异步线程完成,因此,您要么需要自己的等待处理程序/同步方法,要么需要使用.connect而不是async。我将此标记为已回答,尽管这只是我查询的一半,因为我有两个问题:-)谢谢。我最终确实使用了委托,但使用的方式更加简单和直接(请参见我的解决方案编辑)是的,谢谢。基于事件的编程绝对是个好主意
public event EventHandler<MyEventArgs> EventDispatch;
private void HandleConnect(IAsyncResult ar)
{
try
{
ipcState.IpcSocket.EndConnect(ar);
}
catch(Exception x)
{
if (EventDispatch!= null)
{
EventDispatch(this, args);
}
}
}
//Priorly, I push subscriptions like that :
tcpConnector.EventDispatch += tcpConnector_EventDispatch;
public void tcpConnector_EventDispatch(object sender, VfxTcpConnectorEventArgs args)
{
//Notify third parties, manage exception, etc.
}
public void
CallbackMethod
(IAsyncResult AR)
{
// Retrieve the delegate
MyDelegate ThisDelegate =
(MyDelegate)AR.AsyncState;
try
{
Int32 Ret = ThisDelegate.EndInvoke(AR);
} // End try
catch (Exception Ex)
{
ReportException(Ex);
} // End try/catch
} // End CallbackMethod