并行运行多个任务(变量编号),并在完成所有任务后继续

时间:2015-04-17 08:13:25

标签: c# multithreading task-parallel-library task

我需要开一个"数字"任务(变量但小于10)不并行,     并等待他们全部完成,从每个结果得到。     我从每个中获取结果,保存在列表中,然后最终使用它。

这是我的代码,它正在运作,但我认为必须有更清洁的方法。

导致任务数量

List<String> Arguments = new List<String> { "AA", "BB", "CC" }; 

List<String> ResultList = new List<String>();  

//**AT LEAST I'VE GOT ONE**

Task<String> Tasks = Task<String>.Factory.StartNew(() =>
{
    return DoSomething(Arguments[0]);
});

ResultList.Add(Tasks.Result);

for (Int32 i = 1; i < Arguments.Count; i++)
{
    ResultList.Add(Tasks.ContinueWith<String>(Result =>
    {
        return DoSomething(Arguments[i]);

    }).Result);
}

//**DO I NEED THIS?? It's working even without!!**
//Tasks.Wait();

for (Int32 i = 0; i < ResultList.Count; i++)
{
    textBox1.AppendText(ResultList[i] + Environment.NewLine + Environment.NewLine);
}

4 个答案:

答案 0 :(得分:3)

我认为这就是你要做的事情:即开始一大堆并行任务并等待它们全部完成然后继续

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnitTestProject2
{
    class Class4
    {
        public void run()
        {
            List<String> Arguments = new List<String> { "AA", "BB", "CC" };
            List<Task<String>> tasks = new List<Task<string>>();

            foreach (string arg in Arguments)
            {
                    tasks.Add(
                        this.DoSomething(arg)
                        .ContinueWith(t => this.DoSomething(t.Result))
                        .Unwrap<string>()
                    );
            }

            Task.WaitAll(tasks.ToArray());

            foreach(Task<string> t in tasks)
            {
                textBox1 += (t.Result + Environment.NewLine + Environment.NewLine);
            }

        }

        public async Task<string> DoSomething(string arg)
        {
            return arg;
        }

        public string textBox1;
    }
}

答案 1 :(得分:1)

您不需要Wait()来电。 Task<T>.Result州的文档:

  

访问属性的get访问器会阻塞调用线程,直到异步操作完成;它相当于调用Wait方法。

答案 2 :(得分:0)

你可以使用async await

public async List<String> SomeMethod() {
   List<String> Arguments = new List<String> { "AA", "BB", "CC" }; 
   List<String> ResultList = new List<String>();  
   foreach(var argument in Arguments) 
   {
     var result = await DoSomething(argument);
     ResultList.Add(result);
   }
   return ResultList;
}

答案 3 :(得分:0)

截至目前,您的整个代码都是同步运行的。您正在使用Task创建Task.Result,然后主动阻止它。

如果您真正了解并行性是什么,并且您确实需要执行与列表中的参数一样多的任务,那么您可以卸载所有这些任务然后异步等待(这是异步)完成后:

var arguments = new[] { "A", "B", "C" };
var tasks = arguments.Select(argument => Task.Run(() => DoSomething(argument))).ToList();

while (tasks.Count > 0)
{
    var finishedTask = await Task.WhenAny(tasks);
    textBox1.AppendText(string.Format("{0}{1}{1}", finishedTask.Result,
                                                   Environment.NewLine));

    tasks.Remove(finishedTask);
}

修改 来自您的评论:

  

我正在调用一个不允许多次通话的网络API(不是我的)   同时,这就是我需要等待每项任务完成的原因

然后根本不需要每个参数的线程。两件事:

  1. 您可以使呼叫完全同步,因为您必须等待每个呼叫的完成。使用线程池线程只是无用的
  2. 您可以进行异步调用,而无需使用线程。查看HttpClient及其XXXAsync方法(例如GetAsync)。