未知泛型类型的任务的ContinueWith



我有一个方法,它得到一个Task<T>,其中T在编译时是未知的,以及一个IAsyncDisposable。我需要返回一个Task<T>,它在原始任务完成后自动处理一次性对象。

这就是我到目前为止所想到的,但它抛出了一个编译时错误

private static TResult AutoDispose<TResult>(TResult result, IAsyncDisposable asyncDisposable)
{
Func<dynamic, dynamic> continuationFunction = async t => { await asyncDisposable.DisposeAsync(); return ((dynamic)t).Result; };
var autoDisposing = ((dynamic)result).ContinueWith(continuationFunction);
return (TResult)autoDisposing;
}

我得到的错误是

无法将异步lambda表达式转换为委托类型'Func<动态,动态>'。异步lambda表达式可能返回void、Task或Task,它们都不能转换为'Func<动态,动态>'。

我已经尝试了dynamicTask的不同组合,但无法创建有效的解决方案。我总是会遇到编译或运行时错误。

编辑

因为这似乎让人困惑我为什么要这样做:

我在IAsyncQueryProviderExecuteAsync方法中使用这个。接口将方法Signature定义为以下

public TResult ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken = default)

基于此,我知道TResult是类型IAsyncEnumerable<T>Task<T>。当它是IAsyncEnumerable<T>时,我已经编写了处理这种情况的代码,但当它是一个Task<T>时,我仍在挣扎。

若要使用async,编译时结果类型必须是Task(或类似task(。嵌套任务使用ContinueWithasync连续是正常的;CCD_ 17是一种解决方案。如果您可以完全避免ContinueWith,那就更好了,但我相信在这种情况下,这将需要相当多乏味的泛型工作。

像这样的东西应该起作用:

private static TResult AutoDispose<TResult>(TResult result, IAsyncDisposable asyncDisposable) // where TResult: Task<T>
{
Func<dynamic, Task<TResult>> continuationFunction = async () => { await asyncDisposable.DisposeAsync(); return result; };
var continuation = ((dynamic)result).ContinueWith(continuationFunction, TaskScheduler.Default);
var newResult = TaskExtensions.Unwrap(continuation);
return (TResult)newResult;
}

试试这个?

private static async Task<TResult> AutoDispose<TResult>( this Task<TResult> task )
where TResult : IAsyncDisposable
{
TResult result = await task.ConfigureAwait(false);
if( result != null )
{
await result.DisposeAsync().ConfigureAwait(false);
}

return result;
}

示例用法:

Task<HttpResponseMessage> task = new HttpClient()
.GetAsync( "/foo" )
.AutoDispose();
HttpResponseMessage resp = await task;
// `resp` will be in a disposed state at this point.

相关内容

  • 没有找到相关文章

最新更新