Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-异步回调中的异常传播问题_C#_.net - Fatal编程技术网

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
    由框架使用连接的结果调用
  • 当您到达步骤4时,
    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