【问题标题】:populate 2 lists using parallelism使用并行填充 2 个列表
【发布时间】:2020-02-11 13:52:20
【问题描述】:

我有 2 个长期运行的方法,它们从外部来源获取数据并将结果作为列表返回:

public static class Helper1
{
    public static List<X> GetStuff()
    {
        // some long running stuff
    }
}

public static class Helper2
{
    public static List<Y> GetStuff()
    {
        // some long running stuff
    }
}

我想并行而不是顺序运行它们。我的第一次尝试是:

var task1 = new Task>(() => Helper1.GetStuff()); var task2 = new Task>(() => Helper2.GetStuff());

var whenAllTask = Task.WhenAll(task1, task2);

task1.Start();
task2.Start();

似乎什么都没有发生,我想知道之后如何访问列表的内容(程序按顺序继续)。谢谢!

PS:

鉴于 Robin B 的回答,我现在正在使用以下代码:

 var task1 = new Task<List<X>>(() => Helper1.GetStuff(), TaskCreationOptions.LongRunning);
    var task2 = new Task<List<Y>>(() => Helper1.GetStuff(), TaskCreationOptions.LongRunning);

    var whenAllTask = Task.WhenAll(task1, task2).Wait();

    List<X> lst1 = task1.Result;
    List<Y> lst2 = task2.Result;

不幸的是,没有任何反应,它似乎被卡住了。

PPS:

这似乎对我有用:

var task1 = Task.Factory.StartNew<List<X>>(() => Helper1.GetStuff(), TaskCreationOptions.LongRunning));
var task2 = Task.Factory.StartNew<List<Y>>(() => Helper2.GetStuff(), TaskCreationOptions.LongRunning);

var allTasks = new Task[] { task1, task2 };

Task.WaitAll(allTasks);

List<X> lst1 = task1.Result;
List<Y> lst2 = task2.Result;

【问题讨论】:

  • await whenAllTask; 等待task1task2完成
  • 我还建议在创建时指定TaskCreationOptions.LongRunning 标志,这将强制创建一个单独的线程来运行任务。
  • t1t2 未定义。它们与这个问题有关吗?此外,task2 的赋值不会编译,因为Helper1.GetStuff 返回一个List&lt;X&gt;。示例请使用真实代码。
  • @cs0815 这是一个可以传递给Task 构造函数的标志(如果你正在使用它,也可以传递给TaskFactory.StartNew)。所以一个例子是var task1 = new Task&lt;List&lt;X&gt;&gt;(() =&gt; Helper1.GetStuff(), TaskCreationOptions.LongRunning);
  • var task2 = new Task&lt;List&lt;Y&gt;&gt;(() =&gt; Helper1.GetStuff()); - 这不应该是Helper2吗?

标签: c# task-parallel-library


【解决方案1】:

WhenAll 将等待所有给定的running 任务。所以你必须先启动它们。 此外,如果您使用Task&lt;T&gt;,您可以在任务完成后通过读取Task&lt;T&gt;.Result 属性来检索任务的结果。

您还会注意到Task.WhenAll 将返回一个可等待对象。所以你必须在那里打电话给Wait(),否则你就会一发不可收拾。

这是一个例子:

  class Program
  {
    static void Main()
    {
      Task<List<int>> t1 = new Task<List<int>>(GetList);
      Task<List<int>> t2 = new Task<List<int>>(GetList);

      t1.Start();
      t2.Start();

      Task.WhenAll(t1, t2).Wait();

      Console.WriteLine("Both should have ended now");

      List<int> lst1 = t1.Result;
      List<int> lst2 = t2.Result;

      Console.ReadKey(true);
    }

    public static List<int> GetList()
    {
      Console.WriteLine("Started");

      Random rng = new Random();

      List<int> lst = new List<int>();

      for(int i = 0; i < 1000000; i++)
      {
        lst.Add(rng.Next());
      }

      Console.WriteLine("Ended");

      return lst;
    }
  }

编辑 您可能想阅读awaitWait()。我确实暗示您说程序按顺序继续,您处于纯同步上下文中,只需要提高获取性能。但是,如果您从 UI 线程或类似的线程调用此代码,请注意 Wait() 调用会阻塞您的 UI 线程。在这种情况下,使用 await 将是更好的选择。 (await vs Task.Wait - Deadlock?)

【讨论】:

  • 感谢您提供的代码工作正常。但是,在我使用这些静态类和方法的场景中,它似乎不起作用。它只是挂起。我在 List GetStuff() 中设置了一个断点,但它没有被击中。有任何想法吗?谢谢。
【解决方案2】:

更简洁的方法应该是使您的方法异步,以便可以异步调用它们:

public static class Helper1
{
    public static Task<List<string>> GetStuffAsync()
    {
        return Task.Run(() => new List<string>{"78", "98", "56",});
    }
}

public static class Helper2
{
    public static Task<List<int>> GetStuffAsync()
    {
        return Task.Run(() => new List<int>{1, 2, 3, 4, 5, 6});
    }
}

然后像下面这样调用它们。这里的关键是await 关键字,它告诉编译器此时必须完成任务。

static async Task Main(string[] args)
{
    var task1 = Helper1.GetStuff();
    var task2 = Helper2.GetStuff();
    
    await Task.WhenAll(task1, task2);

    Console.WriteLine(task1.Result);
    Console.WriteLine(task2.Result);
}

【讨论】:

    【解决方案3】:

    这似乎对我有用:

    var task1 = Task.Factory.StartNew<List<X>>(() => Helper1.GetStuff(), TaskCreationOptions.LongRunning));
    var task2 = Task.Factory.StartNew<List<Y>>(() => Helper2.GetStuff(), TaskCreationOptions.LongRunning);
    
    var allTasks = new Task[] { task1, task2 };
    
    Task.WaitAll(allTasks);
    
    List<X> lst1 = task1.Result;
    List<Y> lst2 = task2.Result;
    

    【讨论】:

      猜你喜欢
      • 2018-08-23
      • 2022-10-06
      • 2019-10-21
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 2017-01-20
      • 2017-08-01
      • 1970-01-01
      相关资源
      最近更新 更多