【问题标题】:c# asynchronous invoke of generic delegatesc#泛型委托的异步调用
【发布时间】:2020-11-10 09:46:18
【问题描述】:

我想使用async await 调用通用Delegate。我没有使用预构建的委托,而是使用通用的 Delegate 类,它可以接收作为对象数组的参数。

我正在做这样的事情:

public object InvokeAction(Delegate action, object[] actionArgs = null)
    {
        if(action == null)
        {
            return null;
        }
        return action.DynamicInvoke(args);
    }

我想要做的是提供一个使用await 运行委托的选项,但由于DynamicInvoke 返回一个对象,它没有awaiter

有没有办法定义一个通用委托并进行异步调用?如果不是通用的,是否有一些接近通用委托的版本(可以强制用户使用某些委托定义)可以按照我想要的方式调用?

【问题讨论】:

  • 那个action 代表——这实际上是异步的,即它是否返回一个Task
  • 你能分享一个要调用的方法的例子吗?我希望您知道只是因为您等待某些东西不会使该异步。
  • 该操作可以是常规同步调用的任何内容。在异步调用的情况下,我试图检查我是否仍然可以使用相同的通用委托,或者我必须定义一个返回任务并强制用户使用它的委托
  • 我会建议第二种方法InvokeActionAsync。无论如何,你不需要强制用户使用那个,他们当然可以在没有await的情况下调用你的异步方法。

标签: c# asynchronous async-await delegates


【解决方案1】:

您的委托需要返回一个awaitable type,一般是TaskTask<TResult>

您可以在运行时检查:

public async Task<TResult> InvokeAction<TResult>(Delegate action, object[] actionArgs = null)
{
    //...
    var result = action.DynamicInvoke(actionArgs);
    if (result is Task<TResult> task) return await task;
    return (TResult)result;
}

但是,只要 actionArgs 在您的方法中没有被修改,您就可以静态键入您的委托,并使用闭包:

public async Task<TResult> InvokeAction<TResult>(Func<Task<TResult>> action)
{
    //...
    return await action();
}

var result = InvokeAction(() => YourMethodAsync(arg1, arg2));

【讨论】:

    【解决方案2】:

    我假设 IF 目标委托对异步方法的引用(返回 TaskTask&lt;T&gt;)然后您希望异步执行它。然后您可以使用类似于您当前的方法,但它是异步的:

    public static async Task<object> InvokeActionAsync(Delegate action, object[] actionArgs = null)
    {
        if (action == null) {
            return null;
        }
    
        // invoke it
        var result = action.DynamicInvoke(actionArgs);
        if (result == null)
            return null;
        if (result.GetType().IsGenericType && result.GetType().GetGenericTypeDefinition() == typeof(Task<>)) {
            // this is some Task<T> which returns result
            await (Task) result;
            // now need to grab the result
            return result.GetType().GetProperty("Result").GetValue(result);
        }
        else if (result is Task) {
            // it's regular Task which does not return the value
            await (Task) result;
            return null;
        }
        // otherwise nothing to really run async, just return result
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      相关资源
      最近更新 更多