[英]Async version of generic extensions
在C#6中,我具有以下扩展名:
public static void With<T>(this T value, Action<T> action) {
action(value);
}
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
有没有办法拥有这些扩展的异步版本?
UPDATE
我正在添加一个例子来澄清。 考虑(上下文是EF上下文):
IList<Post> posts = context.Posts.With(x => x.ToList());
现在,如果我想使用ToListAsync,该怎么做?
IList<Post> posts = await context.Posts.WithAsync(x => x.ToListAsync());
要么
IList<Post> posts = context.Posts.WithAsync(x => await x.ToListAsync());
最好的方法是什么?扩展的外观如何?
我强烈建议不要在扩展方法中使用async
/ await
来跳过状态机的生成 。 只需返回任务并在需要时等待或await
它们
您也可以将第二种方法用于异步案例
public static R With<T>(this T value, Func<T, R> function)
{
return function(value);
}
或者您可以约束方法仅用于异步使用
public static R WithAsync<T, R>(this T value, Func<T, R> function)
where R : Task
{
return function(value);
}
我有一篇关于异步委托类型的博客文章。 总之, Action<T>
的async
版本是Func<T, Task>
,而Func<T, R>
的async
版本是Func<T, Task<R>>
。
我建议您提供所有重载以最大程度地提高可用性:
public static void With<T>(this T value, Action<T> action) {
action(value);
}
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
public static Task With<T>(this T value, Func<T, Task> function) {
return function(value);
}
public static Task<R> With<T, R>(this T value, Func<T, Task<R>> function) {
return function(value);
}
就像执行其他任何功能一样:
public static async Task With<T>(this T value, Func<T, Task> action) {
await action(value);
}
public static async Task<R> With<T, R>(this T value, Func<T, Task<R>> function) {
return await function(value);
}
async
。 Task
。 如果需要实际的返回类型,请使用Task<InsertReturnTypeHere>
代替Task
WithAsync
。 这将使With<T>
与异步实现共存,这也是常见的约定。 public static async Task WithAsync<T>(this T value, Action<T> action)
{
await actionAsync(value);
}
public static void With<T>(this T value, Action<T> action) {
action(value);
}
让您的操作安排任务本身。 With
预期不会返回任何值,因此不必关心操作如何运行。
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
提供一个返回Task的function
。 您可以像var y = await x.With(async z => { /* ... */ });
一样使用它var y = await x.With(async z => { /* ... */ });
。
结论:您无需进行任何更改。
这取决于您打算执行的处理量以及您打算如何进行处理。
您是否需要线程? 如果是这样,那么使用Task可以很好地替代Thread。
否则,线程池中可能已经有很多线程可供使用, 请参见此问题。您可以使用'BeginInvoke'访问这些线程。
static void _TestLogicForBeginInvoke(int i)
{
System.Threading.Thread.Sleep(10);
System.Console.WriteLine("Tested");
}
static void _Callback(IAsyncResult iar)
{
System.Threading.Thread.Sleep(10);
System.Console.WriteLine("Callback " + iar.CompletedSynchronously);
}
static void TestBeginInvoke()
{
//Callback is written after Tested and NotDone.
var call = new System.Action<int>(_TestLogicForBeginInvoke);
//Start the call
var callInvocation = call.BeginInvoke(0, _Callback, null);
//Write output
System.Console.WriteLine("Output");
int times = 0;
//Wait for the call to be completed a few times
while (false == callInvocation.IsCompleted && ++times < 10)
{
System.Console.WriteLine("NotDone");
}
//Probably still not completed.
System.Console.WriteLine("IsCompleted " + callInvocation.IsCompleted);
//Can only be called once, should be called to free the thread assigned to calling the logic assoicated with BeginInvoke and the callback.
call.EndInvoke(callInvocation);
}//Callback
输出应为:
Output
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
NotDone
IsCompleted False
Tested
Callback False
您可以使用委托实例的“ BeginInvoke”方法在线程池上调用您定义的任何“委托”类型。 另请参见MSDN
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.