问题描述
我试图总结我的周围头异步
/ 伺机
并想知道这是否是正确使用在 Task.WhenAll
方法:
公共类AsyncLib
{
公共异步任务<&IEnumerable的LT;串GT;> DOIT()
{
变种的URL =新的String [] {http://www.msn.com,http://www.google.com};
变种任务= urls.Select(X => this.GetUrlContents(X));
VAR的结果=等待Task.WhenAll(任务);
返回results.Select(X => X);
}
公共异步任务<串GT;使用GetUrlContents(字符串URL)
{
(VAR的客户=新的WebClient())
{
返回等待client.DownloadStringTaskAsync(URL);
}
}
}
主要
这是调用控制台应用程序。
类节目
{
静态无效的主要(字串[] args)
{
变种LIB =新AsyncLib();
的foreach(在lib.DoIt()VAR项目的结果。)
{
Console.WriteLine(item.Length);
}
Console.Read();
}
}
与当前的代码的问题是,你将无法处理个别例外,如果有多个任务抛出。
如果这是一个问题,然后用下面的方法,您可以处理它们:
公共异步任务<任务<串>> DOIT()
{
变种的URL =新的String [] {http://www.msn.com,http://www.google.com};
变种任务= urls.Select(X => this.GetUrlContents(X))ToArray的();
等待Task.WhenAll(任务);
返回任务;
}
// ...
静态无效的主要(字串[] args)
{
变种LIB =新AsyncLib( );
的foreach(在lib.DoIt()VAR项目的结果。)
{
Console.WriteLine(item.Result.Length);
}
Console.Read();
}
请注意我用 ToArray的()
来避免评估枚举和启动任务不止一次(如LINQ是懒惰的评估)。
更新,现在你可以进一步优化 DOIT
通过消除异步/的await
:
公共任务<任务<串GT;> DOIT()
{
变种的URL =新的String [] {http://www.msn.com,http://www.google.com};
变种任务= urls.Select(X => this.GetUrlContents(X))ToArray的();
返回Task.Factory.ContinueWhenAll(
任务,
_ =>的任务,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,TaskScheduler.Default );
}
不过,如果你这样做,要知道在异常传播行为。
I am trying to wrap my head around async
/await
and wanted to know if this is the proper use of the Task.WhenAll
method:
public class AsyncLib
{
public async Task<IEnumerable<string>> DoIt()
{
var urls = new string[] { "http://www.msn.com", "http://www.google.com" };
var tasks = urls.Select(x => this.GetUrlContents(x));
var results = await Task.WhenAll(tasks);
return results.Select(x => x);
}
public async Task<string> GetUrlContents(string url)
{
using (var client = new WebClient())
{
return await client.DownloadStringTaskAsync(url);
}
}
}
Main
This is the calling console application.
class Program
{
static void Main(string[] args)
{
var lib = new AsyncLib();
foreach(var item in lib.DoIt().Result)
{
Console.WriteLine(item.Length);
}
Console.Read();
}
}
The problem with your current code is that you won't be able to handle individual exceptions, if more than one task throws.
If this is a concern, then with the following approach, you can handle them:
public async Task<Task<string>[]> DoIt()
{
var urls = new string[] { "http://www.msn.com", "http://www.google.com" };
var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray();
await Task.WhenAll(tasks);
return tasks;
}
// ...
static void Main(string[] args)
{
var lib = new AsyncLib();
foreach(var item in lib.DoIt().Result)
{
Console.WriteLine(item.Result.Length);
}
Console.Read();
}
Note I use ToArray()
to avoid evaluating the enumerable and starting the tasks for more than once (as LINQ is lazy-evaluated).
Updated, now you can further optimize DoIt
by eliminating async/await
:
public Task<Task<string>[]> DoIt()
{
var urls = new string[] { "http://www.msn.com", "http://www.google.com" };
var tasks = urls.Select(x => this.GetUrlContents(x)).ToArray();
return Task.Factory.ContinueWhenAll(
tasks,
_ => tasks,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
However, if you do so, be aware of the change in the exception propagation behavior.
这篇关于正确使用Task.WhenAll的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!