c# - 如何将异步 Func 或 Action 转换为委托(delegate)并调用它

标签 c# .net asynchronous delegates async-await

我正在努力使这段代码工作:

protected async Task RunIsolated<TServ1, TServ2>(Action<TServ1, TServ2> action)
{
    await RunInScope(action, typeof(TServ1), typeof(TServ2));
}

protected async Task<TResult> RunIsolatedForResult<TService, TResult>(Func<TService, TResult> func)
{
    return (TResult) await RunInScope(func, typeof(TService));
}

private Task<object> RunInScope(Delegate d, params object[] args)
{
     using (var scope = _serviceProvider.CreateScope())
     {
         object[] parameters = args.Cast<Type>().Select(t => scope.ServiceProvider.GetService(t)).ToArray();
         return Task.FromResult(d.DynamicInvoke(parameters));
     }
}

这适用于代码的同步版本,如下所示:

await RunIsolated<Service>(serv => serv.SaveAsync(item).Wait());

但对于相同代码的异步版本不起作用(数据库操作抛出异常)

await RunIsolated<Service>(async serv => await serv.SaveAsync(item));

是否有可能将异步 ActionFunc 转换为 Delegate 并在不丢失异步状态的情况下调用它?

最佳答案

您需要创建接受 Func<Task> 的新重载.现在,您在此处传递的匿名异步函数

await RunIsolated<Service>(async serv => await serv.SaveAsync(item));

被视为Action , 这意味着 async void方法基本上,具有所有相应的缺点。相反,你必须做这样的事情(简化为使用基本的 Action 和 Func,根据你的情况进行调整):

protected Task RunIsolated(Action action) {
    return RunInScope(action);
}

protected Task RunIsolated(Func<Task> action) {
    return RunInScope(action);
}

protected Task<TResult> RunIsolatedForResult<TResult>(Func<Task<TResult>> action) {
    return RunInScopeWithResult<TResult>(action);
}

protected Task<TResult> RunIsolatedForResult<TResult>(Func<TResult> action) {
    return RunInScopeWithResult<TResult>(action);
}

private async Task RunInScope(Delegate d, params object[] args) {
    // do some stuff
    using (var scope = _serviceProvider.CreateScope()) {
        object[] parameters = args.Cast<Type>().Select(t => scope.ServiceProvider.GetService(t)).ToArray();
        var result = d.DynamicInvoke(parameters);
        var resultTask = result as Task;
        if (resultTask != null) {
            await resultTask;
        }
    }
}

private async Task<TResult> RunInScopeWithResult<TResult>(Delegate d, params object[] args) {
    // do some stuff
    using (var scope = _serviceProvider.CreateScope()) {
        object[] parameters = args.Cast<Type>().Select(t => scope.ServiceProvider.GetService(t)).ToArray();
        var result = d.DynamicInvoke(parameters);
        var resultTask = result as Task<TResult>;
        if (resultTask != null) {
            return await resultTask;
        }
        return (TResult) result;
    }
}

关于c# - 如何将异步 Func 或 Action 转换为委托(delegate)并调用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48006972/

相关文章:

c# - .NET 如何在 Azure Windows Server 2012 上解密来自 AT&T gophone 的短信

c# - 动画标题(如泰拉瑞亚的游戏标题)

c++ - 斐波那契的异步​​计算比序列计算慢

android - Cocoa 异步套接字 java 实现

c# - 如何使用 EF6 获取大量记录

c# - 我已经接近界面顿悟了

c# - 使用 GetProperty 语法在 Umbraco 7 中获取媒体 url

c# - WCF SSL 配置可能错误

c# - IParameterInspector .BeforeCall 中的引用类型字段为 null

java - Hystrix 执行模式