通用扩展的异步版本

时间:2016-05-06 16:38:59

标签: c#

在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);
}

有没有办法让这些扩展的Async版本?

更新

我正在添加一个例子来澄清。考虑(上下文是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());

什么是最好的方法,扩展如何?

6 个答案:

答案 0 :(得分:2)

我强烈建议您不要在扩展方法中使用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);
}

答案 1 :(得分:2)

我在asynchronous delegate types上发了一篇博文。总而言之,async Action<T>Func<T, Task>async,而Func<T, R>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); }

我建议您提供所有重载以实现最大可用性:

\s

答案 2 :(得分:0)

就像其他任何功能一样:

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);
}

答案 3 :(得分:0)

  • 制作async
  • 让它返回Task。如果您需要实际的退货类型,请使用Task<InsertReturnTypeHere>代替Task
  • 并且为了更好的衡量标准,请将其命名为WithAsync。这将允许With<T>与异步实现共存,这也是常见的惯例。
public static async Task WithAsync<T>(this T value, Action<T> action) 
{
    await actionAsync(value);
}

答案 4 :(得分:0)

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);
}

提供返回任务的function。您可以像var y = await x.With(async z => { /* ... */ });一样使用它。

结论:您无需进行任何更改。

答案 5 :(得分:0)

这取决于您打算处理的处理量以及您打算如何处理它。

你需要一个线程吗?如果是这样,那么使用Task提供了一个很好的替代线程。

否则,线程池中可能已经有很多线程可供您使用,See this question您可以使用'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