繁体   English   中英

通用扩展的异步版本

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM