使用Parallel Foreach和WhenAny的多个任务.那可能吗?

jua*_*ora 1 .net c# task task-parallel-library c#-5.0

我想同时抓取几个网站,但只是逐个将信息添加到数据库中.同时我的代码看起来类似于:

        List<SiteMetadata> sitesList = GetSites();
        var tasks = new List<Task<SiteMetadata>>();

        foreach (var item in sitesList)
            tasks.Add(item.LoadMetaDataAsync());

        int totalSites = sitesList.Count;
        int finishedSites = 0;

        int errors = 0;
        while (totalSites != finishedSites)
        {
            var tempSite = await Task.WhenAny(tasks.ToArray());
            //WRITE HERE TO DB!!!!!!!!!!!!!!!!!
            tasks.Remove(tempSite);

            var tempLog = apiHandler.WriteToDatabase(tempSite.Result);

            if (tempLog.Type == LogType.Error)
            {
                errors++;
                LogsHandler.AddToLog(tempLog);
            }

            finishedSites++;
        }
Run Code Online (Sandbox Code Playgroud)

我想在这里提高效率并取代:

    var tasks = new List<Task<SiteMetadata>>();
    foreach (var item in sitesList)
        tasks.Add(item.LoadMetaDataAsync());
Run Code Online (Sandbox Code Playgroud)

这样的事情:

    var runAll = Task.Factory.StartNew(() => Parallel.ForEach(sitesList, item => item.LoadMetaDataAsync()));
Run Code Online (Sandbox Code Playgroud)

但问题是我不知道如何逐个完成第一个完成任务和数据库.无论如何使用Parallel或类似的东西,甚至比我现在正在做的更有效的东西?提前致谢.

Ste*_*ary 6

我想同时抓取几个网站,但只是逐个将信息添加到数据库中.

你的代码已经做到了.

我想要的是提高效率并取而代之

这不会提高效率; 它会降低它.Parallel.ForEach是一个并行操作,其中"parallel"表示"并发使用多个线程".启动多个任务然后将它们组合在一起Task.WhenAll就是如何在使用多个线程的情况下进行并发.使用不必要的线程更有效.

但是,看起来你正在做的事情可能会受益于TPL Dataflow,它允许你定义一个"管道"来发送数据.它不会提高你的"效率",但它可能会澄清代码.