2017-05-10 77 views
3

想象一下,你想寫一個類似於下面的方法。它包裝一個函數返回一個ValueTask<T>瑣碎的性能監視代碼:如何編寫一個可以處理Task和ValueTask的方法?

static async Task Measure<T>(Func<ValueTask<T>> body) 
{ 
    Console.WriteLine($"Starting perf test"); 
    var sw = Stopwatch.StartNew(); 
    await body(); 
    sw.Stop(); 
    Console.WriteLine(sw.Elapsed); 
} 

我的問題是:有一次寫這個功能,所以它可以接收Func<ValueTask<T>>Func<Task<T>>的方法嗎?

當然,您可以簡單地複製代碼並更改參數的類型。

static async Task Measure<T>(Func<Task<T>> body) { ... } 

實施將是完全相同的。我在問自己是否有可能在處理ValueTaskTask時避免這種代碼重複。到目前爲止,我無法想出一個好的解決方案。有任何想法嗎?

回答

3

根據官方文檔:Generalized async return types

ValueTask結構有一個Task參數的構造函數,這樣就可以構建從任何現有的異步方法的返回值的ValueTask

那意味着您可以編寫一個過載文件,該文件將包裝body,並且只會調用一種方法來完成工作

static Task Measure<T>(Func<Task<T>> body) 
{ 
    var wrapped =() => new ValueTask<T>(body()); 
    return Measure(wrapped); 
} 

static async Task Measure<T>(Func<ValueTask<T>> body) 
{ 
    Console.WriteLine($"Starting perf test"); 
    var sw = Stopwatch.StartNew(); 
    await body(); 
    sw.Stop(); 
    Console.WriteLine(sw.Elapsed); 
} 
+0

謝謝你的建議。我知道這個ValueTask的構造函數。但是,這增加了一些我想避免的開銷。它必須在ValueTask之上分配一個Task。這消除了ValueTask的優勢。 這是不可能的泛化功能,所以你不需要做這個包裝,對吧? 再次感謝您指出該解決方案。對於很多情況來說,這是一個很好的選擇。 – Rainer

+1

@Rainer ValueTask預計會在極少數情況下使用,所以期待'Task'的方法將是更通用的方法。 'ValueTask'如果您將問題更改爲「我的方法如何處理廣義異步返回類型?」問題變得更加有趣(並且可能令人討厭)。 –

相關問題