Reputation: 83
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!
Upvotes: 7
Views: 3012
Reputation: 941942
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.
Upvotes: 3
Reputation: 81680
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.
Upvotes: 2