来自回调 c# 的未处理的异常错误
我有一个 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 层。
请帮忙。
提前致谢!
I have a 3 tier architecture and send some data in the transport layer (TCP Client) using tcp sockets is this methods asynchronously using BeginSend method.
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;
}
}
}
The callback code SendData() is below
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;
}
}
When the server disconnects, the client does not know until it sends some data, therefore the Connected property is true. Then the line remote.BeginReceive() throws the SocketException which I try to capture and throw a custom exception (sockCommunicationException).
However when I do this I get an unhandled exception. I would like to bubble this error to the UI through the Business layer. When an exception like this is raised in the callback method, where does it get raised to?
How can I avoid this undhandled exception and bubble this exception to the UI layer.
Please help.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,不起作用。回调在线程池线程上执行,没有人捕获异常。例如,您需要引发 UI 可以订阅的事件。需要封送处理,如果需要更新 UI,UI 代码需要使用 Control.BeginInvoke() 之类的东西。
Yes, doesn't work. The callback is executed on a threadpool thread, there's nobody there to catch the exception. You'll need to, say, raise an event that the UI can subscribe to. Marshaling is required, the UI code needs to use something like Control.BeginInvoke() if it needs to update the UI.
这是一个常见的要求。
解决方案通常是通过
SendData
访问某些本地方法来通知客户端操作结果并可能显示在 UI 中。现在您需要在不同的中间层中实现这一目标。您的客户端调用服务器,服务器又调用异步方法并触发操作。如果客户端需要了解结果及其异常,它必须轮询服务器并检查结果 - 并且您必须将结果存储在服务器或某个数据库上,直到客户端超时后检索或丢弃它 - 清理本身变得复杂。
或者,它可以使用双工方法让服务器与客户端进行通信。这个解决方案听起来不错,但公平地说,由于各种原因糟糕,这超出了这个问题的范围。
This is a common requirement.
Solution is usually by
SendData
having access to some local method to notify the client of the result of the operation and possibly showing in the UI.Now you need to achieve this in the middle-tier which is different. Your client calls the server which in turn calls async method and triggers the operation. If the client needs to know about the result and its exceptions, it has to poll the server and check for the result - and you would have to store the result (on the server or some database) until client retrieves it or throw away after a time-out - cleanup itself becomes complex.
Alternatively it could use a Duplex method for the Server to communicate back to the Client. This solution sounds great but to be fair is awful for various reasons which is outside the scope of this question.