我有一个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层。
请帮忙。
提前致谢!
答案 0 :(得分:3)
是的,不起作用。回调是在线程池线程上执行的,没有人可以捕获异常。例如,您需要引发UI可以订阅的事件。需要封送处理,如果需要更新UI,UI代码需要使用类似Control.BeginInvoke()的东西。
答案 1 :(得分:2)
这是一个常见的要求。
解决方案通常由SendData
访问某些本地方法,以通知客户端操作结果并可能在UI中显示。
现在你需要在中间层中实现这一点,不同。您的客户端调用服务器,该服务器又调用异步方法并触发操作。如果客户端需要知道结果及其异常,则必须轮询服务器并检查结果 - 并且您必须将结果(在服务器或某个数据库上)存储到客户端在超时后检索或丢弃 - 清理本身变得复杂。
或者,它可以使用 Duplex 方法让服务器与客户端进行通信。这个解决方案听起来很棒,但公平的是糟糕由于各种原因,超出了这个问题的范围。