【发布时间】:2015-01-30 20:31:40
【问题描述】:
我经常编写具有方便方法的代码,这些方法基本上包装了其他方法。这是一个简单的例子:
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<Response> 时尝试返回Task<ReadOnlyCollection<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 线程上。
有什么好方法可以完成我想做的事情吗?
【问题讨论】:
-
这里只是猜测:
public static async Task<Response> GetResponseAsync(Request fromRequest) { var collection = await GetResponsesAsync(new Request[] { fromRequest }); return collection[0]; });,假设您相应地重命名了不方便方法的async版本。我还没有测试过——它仍然会阻塞吗? -
如果你有
Task.Run(async () => { await Task.Delay(10000); return new Response(); });,这里就不需要Task.Run。如果操作已经是async,则不需要在线程池线程中运行。
标签: c# .net task-parallel-library async-await convenience-methods