【问题标题】:How to create a generic extension method for async methods?如何为异步方法创建通用扩展方法?
【发布时间】:2019-04-09 13:59:29
【问题描述】:

我正在尝试创建一个 .WithDelay(seconds); 方法,我可以在异步方法调用的末尾添加它。

我得到的问题是首先调用异步方法然后延迟发生,我希望它反过来,而不切换调用顺序。

例如,我想要await MyMethod().WithDelay(seconds); 而不是await WithDelay(seconds).MyMethod();

这是我目前所拥有的,它首先调用方法:

public async static Task<T> WithDelay<T>(this Task<T> task, int delay) {
  await Task.Delay(delay);
  return await task;
}

我希望延迟首先发生,然后才是实际运行的方法。

【问题讨论】:

    标签: c# async-await task extension-methods


    【解决方案1】:

    我想要反过来,不切换调用顺序。

    这是不可能的,因为 C# 语言只支持 types 上的扩展方法,而不支持 methods

    您可以获得的最接近的是委托的扩展方法:

    public static async Task<T> WithDelay<T>(this Func<Task<T>> func, int delay) {
      await Task.Delay(delay);
      return await func();
    }
    

    用法仍然很尴尬:

    // Either:
    Func<Task<MyType>> func = MyMethod;
    var result = await func.WithDelay(1000);
    
    // or (assuming "using static"):
    var result = await WithDelay(MyMethod, 1000);
    
    // What you really want, not currently possible:
    // var result = await MyMethod.WithDelay(1000);
    

    对于这种类型相关的情况,它可以帮助先同步解决问题,然后将该解决方案转换为async。如果该语言阻止了一个好的同步解决方案,那么它很可能会阻止一个好的异步解决方案。

    有一个 proposal 用于方法上的扩展方法,但它不是今天语言的一部分。

    【讨论】:

    • 不是我要找的答案,但谢谢。我会放弃寻找。
    【解决方案2】:

    下面会起作用吗?

    public static Task Async<T>(this T o, Action<T> action, CancellationToken token = default) {
      if (token.IsCancellationRequested) {
        return Task.FromCanceled(token);
      }
      try {
        action(o);
        return Task.CompletedTask;
      } catch (Exception e) {
      return Task.FromException(e);
      }
    }
    

    例子:

    public static Task CommitAsync(this IDbTransaction transaction, CancellationToken token = default) 
      => transaction.Async(x=> transaction.Commit(), token);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-26
      • 2020-07-09
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多