2017-05-10 31 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'如果您将问题更改为“我的方法如何处理广义异步返回类型?”问题变得更加有趣(并且可能令人讨厌)。 –

相关问题