我正在为客户端/服务器应用程序中的“客户端”类实现异步命令模式。我过去做过一些套接字编码,我喜欢他们在 Socket / SocketAsyncEventArgs 类中使用的新异步模式。
我的异步方法如下所示:public bool ExecuteAsync(Command cmd);
如果执行未决,则返回 true,如果同步完成,则返回 false。我的问题是:即使发生异常,我是否应该始终调用回调 (cmd.OnCompleted)?还是我应该直接从 ExecuteAsync 抛出异常?
如果您需要,这里有更多详细信息。这类似于使用 SocketAsyncEventArgs,但我的类不是 SocketAsyncEventArgs,而是称为 SomeCmd。
SomeCmd cmd = new SomeCmd(23, 14, 10, "hike!");
cmd.OnCompleted += this.SomeCmd_OnCompleted;
this.ConnectionToServer.ExecuteAsync(cmd);
与 Socket 类一样,如果需要配合回调方法(本例中为 SomeCmd_OnCompleted),可以使用 ExecuteAsync 的返回值来了解操作是否处于挂起状态(true)或操作是否同步完成。
SomeCmd cmd = new SomeCmd(23, 14, 10, "hike!");
cmd.OnCompleted += this.SomeCmd_OnCompleted;
if( this.ConnectionToServer.ExecuteAsync(cmd) )
{
Monitor.Wait( this.WillBePulsedBy_SomeCmd_OnCompleted );
}
这是我的基类的一个大大简化的版本,但你可以看到它是如何工作的:
class Connection
{
public bool ExecuteAsync(Command cmd)
{
/// CONSIDER: If you don't catch every exception here
/// then every caller of this method must have 2 sets of
/// exception handling:
/// One in the handler of Command.OnCompleted and one where ExecuteAsync
/// is called.
try
{
/// Some possible exceptions here:
/// 1) remote is disposed. happens when the other side disconnects (WCF).
/// 2) I do something wrong in TrackCommand (a bug that I want to fix!)
this.TrackCommand(cmd);
remote.ServerExecuteAsync( cmd.GetRequest() );
return true;
}
catch(Exception ex)
{
/// Command completing synchronously.
cmd.Completed(ex, true);
return false;
}
}
/// <summary>This is what gets called by some magic when the server returns a response.</summary>
internal CommandExecuteReturn(CommandResponse response)
{
Command cmd = this.GetTrackedCommand(response.RequestId);
/// Command completing asynchronously.
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();
}