2017-08-27 94 views
2

我讀過this question但在我的情況下它更簡單,因爲我不必使用Result屬性。所以我想知道是否可以採用比斯蒂芬·克利裏的答案更簡單的方法。將任務轉換爲任務<T>(包裝任務返回類型T)

假設我有這個簡單的接口。

internal interface IBinaryDataReadable 
{ 
    Task Load(AsyncDataReader reader); 
} 

該接口提供方法異步加載對象。它不會返回任何東西,因爲加載結果是對象本身。

(該接口是內部和爲此實現明確地避免暴露實現)

這是我如何加載的二進制數據。

data = new BinaryData(); 
await ((IBinaryDataReadable)data).Load(reader); 

我想使這個更流暢和詳細,所以我寫這擴展方法

internal static Task<TData> Load<TData>(this TData data, AsyncDataReader reader) 
    where TData : IBinaryDataReadable 
     => data.Load(reader).ContinueWith(t => data, TaskContinuationOptions.ExecuteSynchronously); 

現在正在加載變成這樣。

data = await new BinaryData().Load(reader); 

這裏有什麼我應該擔心使用這種方法?例如異常處理等?

回答

4

釷同樣可以使用異步完成/等待和foregoes使用ContinueWith

internal static async Task<TData> Load<TData>(this TData data, AsyncDataReader reader) 
    where TData : IBinaryDataReadable { 
    await data.Load(reader); 
    return data; 
} 

這樣,你甚至還可以包括異常,如果需要的話在方法中處理。 然而,擴展方法在流暢接口方面做得並不多,因爲該方法返回需要等待的任務。

而且您必須顯式調用通用擴展,否則您只是在等待導致編譯錯誤時解析爲void的類型上調用本地成員。

data = await new BinaryData().Load<BinaryData>(reader); 

我建議將擴展方法重命名爲不會與接口上現有成員衝突的方法。

data = await new BinaryData().LoadAsync(reader); 

我想知道,如果使用的ContinueWith引入問題

我沒有看到它引入除了不能夠逮住例外任何問題。但是,可以通過檢查該案件並將其冒泡來進行管理。

internal static Task<TData> LoadAsync<TData>(this TData data, AsyncDataReader reader) 
    where TData : IBinaryDataReadable { 
    return data.Load(reader) 
     .ContinueWith(t => { 
      var error = t.Exception; 
      if (error != null && t.IsFaulted) 
       throw error; 
      return data; 
     }, TaskContinuationOptions.ExecuteSynchronously); 
} 

雖然在我看來,使用異步/等待是一個更清潔,更容易閱讀和實施。

+0

謝謝。我避免使用async/await的原因是爲了防止爲非常基本的任務生成狀態機開銷,但這是一個很好的解決方案,我想知道是否使用ContinueWith引入了問題。 –

+1

@ M.kazemAkhgary,不,我沒有看到它引入了任何問題,除了無法控制異常 – Nkosi

相關問題