簡體   English   中英

將任務轉換為任務 <T> (包裝任務,返回類型為T)

[英]Convert Task to Task<T> (Wrap Task with return type of T)

我已經閱讀了這個問題,但就我而言,它比較簡單,因為我不必使用Result屬性。 所以我想知道是否可以采用比Stephen Cleary的答案所提供的方法更簡單的方法。

假設我有這個簡單的界面。

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

這里是否有我需要擔心使用此方法的問題?例如異常處理等?

可以使用async / await完成此操作,並使用ContinueWith放棄

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

這樣,如果需要,您甚至可以在方法中包括異常處理。 但是,擴展方法在流暢的界面方面做不到很多,因為該方法返回需要等待的Task。

而且,您將必須顯式地調用通用擴展名,否則,您將僅調用該類型的本地成員,該類型將在等待導致編譯錯誤時解析為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);
}

雖然在我看來,使用async / await更加整潔,更易於閱讀和實現。

暫無
暫無

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

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