来自回调 c# 的未处理异常错误

Posted

技术标签:

【中文标题】来自回调 c# 的未处理异常错误【英文标题】:Unhandled Exception error from a callback c# 【发布时间】:2010-12-12 18:13:50 【问题描述】:

我有一个 3 层架构并使用 tcp 套接字在传输层(TCP 客户端)发送一些数据,这种方法使用 BeginSend 方法异步发送。

public void TransportData(Stream stream)

    try
    
        SetTransporterState(StateObject.State.SendingData);
        if (clientSock.Connected)
        
            ASCIIEncoding asen = new ASCIIEncoding();
            stream.Position = 0;
            byte[] ba = GetStreamAsByteArray(stream);
           if (clientSock.Connected)
              clientSock.BeginSend(ba, 0, ba.Length, SocketFlags.None, new AyncCallback(SendData), clientSock);
           else
               throw new SockCommunicationException("Socket communication failed");

         
         catch (SocketException sex)
         
             throw sex;
         
         catch (SockCommunicationException comex)
         
             bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy");
         if (rethrow)
         
             throw;
         
       
     
   
   catch (SocketException soex)
   
     throw soex;
   
   catch (SockCommunicationException comex)
   
      bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy");
      if (rethrow)
      
         throw;
                      
    
    catch (Exception ex)
    
       LoggingMessageHelper.LogDeveloperMessage(ex.Message + Environment.NewLine + ex.StackTrace, 1, TraceEventType.Critical);
        bool rethrow = ExceptionPolicy.HandleException(ex, "TransportLayerPolicy");
        if (rethrow)
        
          throw;
        
     
  

回调代码SendData()如下

    private void SendData(IAsyncResult iar)
    
        Socket remote = null;
        try
        
            remote = (Socket)iar.AsyncState;
            try
            
                int sent = remote.EndSend(iar);
            
            catch (Exception ex)
            
                throw ex;
            

            if (remote.Connected )
            
                remote.BeginReceive(data, 0, size, SocketFlags.None,
                              new AsyncCallback(ReceiveData), remote); 
            
            else
                throw new SockCommunicationException("Communication Failed");
        
        catch (SocketException soex)
        
            throw new SockCommunicationException("Communication Failed");
        
        catch (SockCommunicationException comex)
        
            bool rethrow = ExceptionPolicy.HandleException(comex, "TransportLayerPolicy");
            if (rethrow)
            
                throw;
            
        

当服务器断开连接时,客户端直到发送一些数据才知道,因此 Connected 属性为 true。然后 remote.BeginReceive() 行抛出我尝试捕获的 SocketException 并抛出自定义异常 (sockCommunicationException)。

但是,当我这样做时,我得到了一个未处理的异常。我想通过业务层将此错误冒泡到 UI。当回调方法中引发这样的异常时,它会引发到哪里?

我怎样才能避免这个未处理的异常并将这个异常冒泡到 UI 层。

请帮忙。

提前致谢!

【问题讨论】:

【参考方案1】:

是的,不起作用。回调在线程池线程上执行,没有人可以捕获异常。例如,您需要引发 UI 可以订阅的事件。需要编组,如果 UI 代码需要更新 UI,则需要使用 Control.BeginInvoke() 之类的东西。

【讨论】:

谢谢,当涉及到 UI 时,我可以通过检查是否 InvokeRequired 并使用委托相应地处理它来处理它。引发事件是将错误冒泡到业务层并从那里到 UI 的最佳方法吗? 好的...再次感谢汉斯!我在想 .NET 框架中是否有一些内置方法可以在不使用事件的情况下处理这样的事情。【参考方案2】:

这是一个常见的要求。

解决方案通常是通过SendData 访问一些本地方法来通知客户端操作结果并可能显示在 UI 中。

现在您需要在中间层实现这一点,这是不同。您的客户端调用服务器,服务器又调用异步方法并触发操作。如果客户端需要了解结果及其异常,它必须轮询服务器并检查结果 - 您必须将结果存储(在服务器或某个数据库上)直到客户端超时后检索或丢弃 - 清理本身变得复杂。

或者,它可以使用 Duplex 方法让服务器与客户端进行通信。这个解决方案听起来不错,但公平地说是 糟糕 出于各种原因,这超出了这个问题的范围。

【讨论】:

嗨 Aliostad,您是说我在传输层中有一个委托,并在发生此错误时引发业务层订阅的事件? 不,我的首选方法是让客户端在必须知道结果时轮询服务器。 很抱歉我没听明白。如果我之前没有解释清楚,客户端会发送请求,服务器会回复它已断开客户端连接的错误。这就是为什么我收到消息“已建立的连接被主机中的软件中止”和错误代码“10053”引发的套接字异常。我仅在回调方法中的 remote.BeginReceive() 行中抛出此错误。我只需要向上冒泡。 那么你在哪里发布了这两种方法?它是在 UI 客户端上还是在暴露为 WCF、... 服务的服务器上? 好的,所以忽略我的大部分答案,除了“解决方案通常是通过 SendData 访问某些本地方法来通知客户端操作结果并可能显示在 UI 中。”此方法将使用 Invoke 来更新 UI。

以上是关于来自回调 c# 的未处理异常错误的主要内容,如果未能解决你的问题,请参考以下文章

来自 MFC 对话框中使用的托管 C# 用户控件的未处理异常

未知模块中发生“System.IO.FileNotFoundException”类型的未处理异常

静默“未知模块中发生‘System.ExecutionEngineException’类型的未处理异常”错误

“创建后”触发器中的未处理异常阻止创建

C#、MAF、单独 AppDomain 中的未处理异常管理

UWP:未指定的错误 - 来自 HRESULT 的异常:0x80004005