gpt4 book ai didi

c# - 转换使用任务的便捷方法

转载 作者:行者123 更新时间:2023-11-30 14:53:54 24 4
gpt4 key购买 nike

我经常编写具有便利方法的代码,这些方法基本上包装了其他方法。这是一个简单的例子:

public class WithoutAsync
{
public static ReadOnlyCollection<Response> GetResponses(IEnumerable<Request> fromRequests)
{
var ret = new List<Response>();

foreach (Request r in fromRequests)
{
ret.Add(new Response());
}

return ret.AsReadOnly();
}

//convenience method
public static Response GetResponse(Request fromRequest)
{
return GetResponses(new Request[] {fromRequest})[0];
}
}

现在我要await长时间运行的操作,但我不太清楚如何改进此方法以用于 TPL:

public class WithAsync
{
public static async Task<ReadOnlyCollection<Response>> GetResponses(IEnumerable<Request> fromRequests)
{
var awaitableResponses = new List<Task<Response>>();

foreach (Request r in fromRequests)
{
awaitableResponses.Add(Task.Run<Response>(async () =>
{
await Task.Delay(10000); //simulate some long running async op.
return new Response();
}));
}

return new List<Response>(await Task.WhenAll(awaitableResponses)).AsReadOnly();
}

//convenience method
public static Task<Response> GetResponse(Request fromRequest)
{
return GetResponse(new Request[] { fromRequest });
}
}

上面的便捷方法显然行不通,因为它试图返回一个 Task<ReadOnlyCollection<Response>>。当它真的需要返回 Task<Response> 时.

这个有效:

//convenience method
public static Task<Response> GetResponse(Request fromRequest)
{
return new Task<Response>(new Func<Response>(() => GetResponse(new Request[] { fromRequest }).Result[0]));
}

但它看起来真的很尴尬,更重要的是,它阻塞在.Result[0]上。这可能在 UI 线程上。

有什么好的方法可以完成我想做的事情吗?

最佳答案

您试图避免使“便捷方法”async,但没有理由这样做。

你想要的是调用另一个方法,等到有响应,然后得到第一个也是唯一一个。您可以通过使其成为 async 并使用 await 来做到这一点:

async Task<Response> GetResponseAsync(Request fromRequest)
{
var responses = await GetResponsesAsync(new[] { fromRequest });
return responses.Single();
}

虽然在这种特定情况下更好的解决方案是切换事物并让单个 GetResponse 实际上完成单个请求的工作,并让多个 GetRsponses 调用而是:

async Task<ReadOnlyCollection<Response>> GetResponsesAsync(IEnumerable<Request> fromRequests)
{
return (await Task.WhenAll(fromRequests.Select(GetResponse))).ToList().AsReadOnly();
}

async Task<Response> GetResponseAsync(Request fromRequest)
{
await Task.Delay(10000); //simulate some long running async op.
return new Response();
}

注意事项:

  • 我知道这是一个示例,但可能没有理由使用 Task.Run 而不是简单的 async 调用。
  • 惯例是使用“Async”后缀命名 async 方法(即 GetResponseAsync)。
  • 我还将返回集合的方法的名称复数化。

关于c# - 转换使用任务的便捷方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28244114/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com