簡體   English   中英

如何將異步Func或Action轉換為委托並調用它

[英]how to cast async Func or Action to Delegate and invoke it

我正在嘗試使這段代碼工作:

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

但是對於相同代碼的異步版本,不起作用(db操作拋出異常)

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

是否有可能將async 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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM