7

我有一个 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 层。

请帮忙。

提前致谢!

4

2 回答 2

3

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

于 2010-12-12T18:26:07.693 回答
2

这是一个常见的要求。

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

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

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

于 2010-12-12T18:24:26.410 回答