本文介绍了正确使用Task.WhenAll的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图总结我的周围头异步 / 伺机并想知道这是否是正确使用在 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的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 08:25
查看更多