2016-11-07 56 views
3
public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(this Task<IEnumerable<T>> obj) where T : class 
{ 
    var first = await Task.WhenAny(obj); 

    return first?.Result?.FirstOrDefault() ?? null; 
} 

這裏有2層其他的方法來顯示完整的這真的是異步嗎? IEnumerable的<T>擴展

主要方法

private async Task<IEnumerable<T>> fetchRecordsAsync(SqlCommand SqlCommand, bool isSingleRecord) 
{..some code...} 
(在這種情況下,將集合或集合空在只返回項)

這裏是來電者只會收取並通過T:

protected async Task<T> GetSingleRecord(SqlCommand SqlCommand) 
{ 
    return await fetchRecordsAsync(SqlCommand, true).FirstIfNotNullOrEmptyAsync(); 
} 

這是正確的方式來處理IEnumerable的異步擴展或它將做同步?

我是否真的需要創建另一個任務(第一個)?

+0

直到任務完成後,它纔會繼續。 –

+1

您的意思是*這個IEnumerable > obj *的論點? – Clay

+0

你會怎麼稱呼這個方法?你如何通過'任務>'? –

回答

3

這真的是異步嗎?

是的。 await Task.WhenAny將返回完成的第一個任務。在這樣的任務(完成的任務)上使用.Result不會導致同步等待。

BTW,你不需要使用Task.WhenAny,你的方法可以簡化如下:

public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(
    this Task<IEnumerable<T>> obj) where T : class 
{ 
    var result = await obj; 

    return result?.FirstOrDefault(); 
} 
+0

@Jonesopolis,「表示任務提供完成的任務」表示一個不完整的任務(除非一個輸入任務已完成)。當任何輸入任務完成時,該任務將完成。 –

+2

不會有不完整的任務,因爲OP只將一個任務傳遞給'WhenAny()'。但是,在這裏使用'WhenAny()'是無稽之談。 – JLRishe

+0

@JLRishe,在調用Task.WhenAny之前,異步數據庫訪問完成的可能性很小。 –

2

它會做所有的工作中以異步方式,雖然有很多有這就是不必要的(雖然無害,除非額外的額外開銷)。

當你只傳遞一個任務時,呼叫WhenAny毫無意義。你可能只是在等待任務本身;它做同樣的事情。

書寫?? null是毫無意義的。如果值爲null使其爲null。它已經是null,所以你可以離開它。

你也沒有通過一個空TaskFirstIfNotNullOrEmptyAsync,你真的不應該。結果你也可能不應該產生nullIEnumerable。如果沒有物品,你應該有一個空的序列。

也沒有理由限制該方法僅適用於類的序列。如果有人想使用價值類型,那麼沒有真正的理由來阻止它們。

調整方法的名稱也是有意義的,因此它的名稱反映了它實際上在做什麼。

所以現在所有這一切都可以直接歸結爲:

public static async Task<T> FirstOrDefaultAsync<T>(this Task<IEnumerable<T>> task) 
{  
    return (await task).FirstOrDefault(); 
} 

您的其他方法也沒有理由async,因爲你永遠不會做與期待已久的任何有價值的東西,除了重新包裝它一個Task並返回它。只需返回您所擁有的Task

protected Task<T> GetSingleRecordAsync(SqlCommand SqlCommand) 
{ 
    return fetchRecordsAsync(SqlCommand, true) 
     .FirstOrDefaultAsync(); 
}