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

Daz*_*ddy 3 c# multithreading asynchronous async-await .net-4.5

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

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

private List<ICommandItem> _items;

private void ProcessCommands()
{
    while(_items.count > 0)
    {
        _items[0].Execute();
        _items.RemoveAt(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ste*_*ary 7

我的问题是我的一些ICommandItem.Execute()方法现在需要异步,因为它们涉及文件io而其他人没有异步方法.

从技术上讲,异步( - Task返回)签名仅表示实现可能是异步的.因此,虽然您可以引入单独的异步接口,但另一种方法是将现有接口更改为 - Task返回:

interface ICommandItem
{
  Task ExecuteAsync(); // Used to be "void Execute();"
}
Run Code Online (Sandbox Code Playgroud)

您的同步实现必须更改为返回Task:

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

虽然异步实现很简单:

async Task ICommandItem.ExecuteAsync()
{
  await ...; // Do asynchronous work.
}
Run Code Online (Sandbox Code Playgroud)

而你的"跑步者"可以使用await:

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