簡體   English   中英

如何使用async / await實現命令模式

[英]How to implement Command Pattern with async/await

我目前正在升級一些現有的代碼供windows universal使用,我正在努力轉換命令模式以使用新的async / await功能。

我有一個命令調度程序類,它在自己的線程中運行並處理已添加到其隊列中的命令。 有問題的方法如下:

private List<ICommandItem> _items;

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

我的問題是我的一些ICommandItem.Execute()方法現在需要異步,因為它們涉及文件io而其他人沒有異步方法。 我怎么能修改上面的模式,以便:

  1. 我的執行程序可以處理異步和非異步ICommandItems
  2. 執行程序僅在前一個命令完成后才開始執行命令。

我很樂意同步執行這些方法但現在到處都會導致死鎖。

我的問題是我的一些ICommandItem.Execute()方法現在需要異步,因為它們涉及文件io而其他人沒有異步方法。

從技術上講,異步( Task -returning)簽名僅表示實現可能是異步的。 因此,雖然您可以引入單獨的異步接口,但另一種方法是將現有接口更改為Task -returning:

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);
    }
}

當然,這假設您可以自由地修改特定的命令類來實現新接口。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM