如何用async/await实现命令模式
本文关键字:实现 命令 模式 await 何用 async | 更新日期: 2023-09-27 18:22:30
我目前正在升级一些现有代码以供windows通用使用,并且正在努力转换命令模式以使用新的async/await功能。
我有一个命令调度程序类,它在自己的线程中运行,并处理添加到队列中的命令。有问题的方法看起来像这样:
private List<ICommandItem> _items;
private void ProcessCommands()
{
while(_items.count > 0)
{
_items[0].Execute();
_items.RemoveAt(0);
}
}
我的问题是,我的一些ICommandItem.Execute()方法现在需要异步,因为它们涉及文件io,而其他方法没有异步方法。我如何修改上面的模式以便:
- 我的执行器可以处理异步和非异步ICommandItems
- 执行器只有在上一个命令完成后才开始执行该命令
我很乐意同步执行这些方法,但现在这会导致到处出现死锁。
我的问题是,我的一些ICommandItem.Execute()方法现在需要异步,因为它们涉及文件io,而其他方法没有异步方法。
从技术上讲,异步(Task
-返回)签名只意味着实现可能是异步的。因此,虽然您可以引入一个单独的异步接口,但另一种方法是将现有接口更改为Task
-返回:
interface ICommandItem
{
Task ExecuteAsync(); // Used to be "void Execute();"
}
您的同步实现必须更改才能返回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.
}
您的"跑步者"只需使用await
:
private async Task ProcessCommandsAsync()
{
while(_items.count > 0)
{
await _items[0].ExecuteAsync();
_items.RemoveAt(0);
}
}
您可以提供第二个接口,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);
}
}
当然,这是假设您可以自由地修改特定的命令类来实现新接口。