2015-11-18 68 views
3

我目前正在升級一些現有的代碼供Windows通用,我正在努力轉換命令模式以使用新的異步/等待功能。如何實現命令模式與異步/等待

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

private List<ICommandItem> _items; 

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

我的問題是,我的一些ICommandItem.Execute的()方法,現在需要異步,因爲它們涉及文件IO,而其他沒有異步方法。我怎麼能修改上面的圖案,使得:

  1. 我的遺囑執行人可以處理異步和非異步ICommandItems
  2. 執行人只有當先前的命令已經完成啓動命令的執行。

我很樂意只是同步執行這些方法,但現在會導致無處不在的死鎖。

回答

6

我的問題是,我的一些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); 
    } 
} 
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); 
    } 
} 

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

+1

的問題,這是返回類型兩者的Execute方法是不同的(一個返回的任務)。我想我可以從一個共同的父界面派生IAsyncCommandItem和ICommandItem,但我希望有一個更優雅的解決方案。 –

+0

@DazEddy - 都返回相同的東西。 await會將任務轉換爲實際返回的項目。 –