如何使用 async/await 实现命令模式

How to implement Command Pattern with async/await

我目前正在升级一些现有代码以供 windows 通用使用,并且正在努力转换命令模式以使用新的 async/await 功能。

我有一个命令调度程序 class,它在自己的线程中运行并处理已添加到其队列中的命令。有问题的方法如下所示:

private List<ICommandItem> _items;

private void ProcessCommands()
{
    while(_items.count > 0)
    {
        _items[0].Execute();
        _items.RemoveAt(0);
    }
}

我的问题是我的一些 ICommandItem.Execute() 方法现在需要异步,因为它们涉及文件 io 而其他方法没有异步方法。我怎样才能修改上面的模式,以便:

  1. 我的执行程序可以处理异步和非异步 ICommandItems
  2. 执行器仅在前一个命令完成后才开始执行命令。

我很乐意只同步执行这些方法,但现在到处都会导致死锁。

您可以提供第二个接口,IAsyncCommandItem:

public interface IAsyncCommandItem : ICommandItem
{
}

在你的 while 循环中,检查项目是否实现了这个接口,并处理它:

private async void ProcessCommands()
{
    while(_items.count > 0)
    {
        var command = _items[0] as IAsyncCommandItem;
        if (command != null)
        {
            await command.Execute();
        }
        else
        {
            _items[0].Execute();
        }
        _items.RemoveAt(0);
    }
}

当然,这假定您可以自由修改特定命令 类 以实现新界面。

My problem is that some of my ICommandItem.Execute() methods now need to be async because they involve file io whilst others have no async methods.

从技术上讲,异步(Task-returning)签名只意味着实现可能是异步的。因此,虽然您可以引入一个单独的异步接口,但另一种方法是将现有接口更改为 Task-returning:

interface ICommandItem
{
  Task ExecuteAsync(); // Used to be "void Execute();"
}

您的同步实现必须更改为 return a Task:

Task ICommandItem.ExecuteAsync()
{
  // Do synchronous work.
  return Task.CompletedTask; // If you're not on 4.6 yet, you can use "Task.FromResult(0)"
}

虽然异步实现很简单:

async Task ICommandItem.ExecuteAsync()
{
  await ...; // Do asynchronous work.
}

而你的 "runner" 可以只使用 await:

private async Task ProcessCommandsAsync()
{
  while(_items.count > 0)
  {
    await _items[0].ExecuteAsync();
    _items.RemoveAt(0);
  }
}