C#中的命令模式和异步操作处理

fer*_*ero 5 c# design-patterns asynchronous

我想听听有关使用Command模式处理异步操作的最佳方法的意见。假设我们有以下示例:

public class MyCommand 
{
   // Sets up receiver and does whatever stuff

   public void Execute()
   {  
       _myReceiver.DoSomething();
   } 
}
Run Code Online (Sandbox Code Playgroud)

问题是:MyCommand不知道MyReceiver.DoSomething()是否具有代码的异步部分。如果我想在MyCommand执行之后将MyCommand推入撤消堆栈,则无法保证其接收者动作已完全执行,因此不确定MyCommand是否已达到可以撤消的状态。

我个人认为以下解决方案:

  1. 在Command中实现某种状态控制
  2. 在命令中包括“ BeginExecute”和“ EndExecute”
  3. 在MyReceiver中包括事件并使Command对其进行订阅(对我来说这似乎很臭)

总结一下,MyCommand会变成:

public class MyCommand 
{
   public MyCommand(MyReceiver receiver)
   {   
      _myReceiver = receiver;
      _myReceiver.DoSomethingFinished += () => this.EndExecute(); 
   }

   public void BeginExecute()
   {  
       this.EnterExecutionState();

       _myReceiver.DoSomething();
   } 

   public void EndExecute()
   {  
       this.LeaveExecutionState();
   } 

   // State handling related stuff
}
Run Code Online (Sandbox Code Playgroud)

现在,我可以确保命令的接收方已经完成了任何操作,并准备将其推入撤消堆栈。但是,对于事件垃圾邮件,每一个包含异步操作的Receiver类的确给我带来了麻烦。

我在Internet上没有找到太多有关此主题的信息,很想听听其他方法。

OBS:不能使命令管理所有与异步相关的代码:)。

Eup*_*ric 1

像这样的东西吗?

public interface ICommand
{
    void Execute();
    event EventHandler Finished;
}

public class MyCommand : ICommand
{
   public MyCommand(MyReceiver receiver)
   {   
      _myReceiver = receiver;
      _myReceiver.DoSomethingFinished += () => Finished(); // dont forget null check here.
   }

   public void Execute()
   {      
       _myReceiver.DoSomething();
   } 

   public event EventHandler Finished;
}
Run Code Online (Sandbox Code Playgroud)

这样,该命令的用户可以注册到 Finished 事件,以便知道命令何时完成其异步行为并可以采取相应的操作。

或者如果你不想使用事件,那么回调呢?

public class MyCommand : ICommand
{
   public MyCommand(MyReceiver receiver)
   {   
      _myReceiver = receiver;
   }

   public void Execute()
   {      
       _myReceiver.DoSomething(() => Finished()); // dont forget null check here.
   } 

   public event EventHandler Finished;
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,MyReciever 只需要有一种方法来通知其调用者它已完成。没有办法绕过它。