C#-将异步任务从一种类型转换为另一种类型

本文关键字:一种 类型转换 类型 另一种 异步 任务 C#- | 更新日期: 2023-09-27 17:59:10

我习惯于使用Scala编程语言——使用Scala我可以映射未来,例如:

val response: Future[HttpResponse] = asyncHttpClient.GetRequest("www.google.com")
val statusCode: Future[Int] = response.map(r => r.statusCode)

最近,我开始使用C#,我发现自己的处境与上面的例子相同,但我不知道如何"映射"任务。

下面是我想要实现的一个例子:

Task<HttpResponseMessage> response = httpClient.GetAsync("www.google.com")
Task<int> statusCode = response.Map(response => response.StatusCode)

感谢

C#-将异步任务从一种类型转换为另一种类型

现有方法最直接的翻译是:

Task<int> statusCode = response.ContinueWith(t => t.Result.StatusCode)

然而,在实践中,你几乎总是在等待任务的结果。也许您应该研究async/await。

老实说,我有点惊讶框架中没有任何内容。(更有可能的是,还有一个我没有见过的。)不过你可以很容易地构建它:

public static async Task<TResult> Map<TSource, TResult>
    (Task<TSource> task, Func<TSource, TResult> selector)
    => selector(await task.ConfigureAwait(false));

注意:这里使用ConfigureAwait并不总是明确的。您可能需要包含continueOnCapturedContext参数:

public static async Task<TResult> Map<TSource, TResult>(
    Task<TSource> task,
    Func<TSource, TResult> selector,
    bool continueOnCapturedContext = false) =>
    selector(await task.ConfigureAwait(continueOnCapturedContext));

使用现代C#,应该使用await:重写

var response = await httpClient.GetAsync("www.google.com")
var statusCode  = response.StatusCode;

这可以与async一起使用,以创建Task<int>:

async Task<int> Fetch(string url)
{
    var response = await httpClient.GetAsync(url);
    return response.StatusCode;
}