I am implementing an asynchronous command template for the client class in a client / server application. In the past, I did some encoding of sockets, and I like the new Async pattern that they used in the Socket / SocketAsyncEventArgs classes.
My async method is as follows: public bool ExecuteAsync(Command cmd);It returns true if execution is pending and false if it is completed synchronously. My question is: should I always call a callback (cmd.OnCompleted) even in case of an exception? Or should I throw exceptions from ExecuteAsync?
Here are some details if you need them. This is similar to using SocketAsyncEventArgs, but instead of SocketAsyncEventArgs, my class is called SomeCmd.
SomeCmd cmd = new SomeCmd(23, 14, 10, "hike!");
cmd.OnCompleted += this.SomeCmd_OnCompleted;
this.ConnectionToServer.ExecuteAsync(cmd);
As with the Socket, if you need to coordinate your callback method (SomeCmd_OnCompleted in this case), you can use the return value of ExecuteAsync to find out if the operation is expecting (true) or if the operation completed synchronously.
SomeCmd cmd = new SomeCmd(23, 14, 10, "hike!");
cmd.OnCompleted += this.SomeCmd_OnCompleted;
if( this.ConnectionToServer.ExecuteAsync(cmd) )
{
Monitor.Wait( this.WillBePulsedBy_SomeCmd_OnCompleted );
}
Here is a very simplified version of my base classes, but you can see how this works:
class Connection
{
public bool ExecuteAsync(Command cmd)
{
try
{
this.TrackCommand(cmd);
remote.ServerExecuteAsync( cmd.GetRequest() );
return true;
}
catch(Exception ex)
{
cmd.Completed(ex, true);
return false;
}
}
internal CommandExecuteReturn(CommandResponse response)
{
Command cmd = this.GetTrackedCommand(response.RequestId);
cmd.Completed(response, false);
}
private IServer remote;
}
abstract class Command: EventArgs
{
internal void Completed(Exception ex, bool synchronously)
{
this.Exception = ex;
this.CompletedSynchronously = synchronously;
if( this.OnCompleted != null )
{
this.OnCompleted(this);
}
}
internal void Completed(CommandResponse response, bool synchronously)
{
this.Response = response;
this.Completed(response.ExceptionFromServer, synchronously)
}
public bool CompletedSynchronously{ get; private set; }
public event EventHandler<Command> OnCompleted;
public Exception Exception{ get; private set; }
internal protected abstract CommandRequest GetRequest();
}