首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Task.WaitAll方法与Parallel.Invoke方法

Task.WaitAll方法与Parallel.Invoke方法
EN

Stack Overflow用户
提问于 2013-04-19 17:48:21
回答 2查看 21.5K关注 0票数 32

我有示例代码来比较并行方法和任务方法的处理时间。本实验的目标是了解它们是如何工作的。

所以我的问题是:

  1. 为什么并行比任务工作得更快?
  2. 我的结果是否意味着我应该使用并行而不是任务?
  3. 我应该在哪里使用任务,在哪里使用并行?
  4. 与并行相比,使用任务有什么好处?
  5. 任务只是ThreadPool.QueueUserWorkItem方法的包装吗?

公共任务SomeLongOperation() { return Task.Delay(3000);} static void Main(string[] args) { Program p=新程序();列表任务=新列表();tasks.Add(Task.Factory.StartNew(() => p.SomeLongOperation();tasks.Add(Task.Factory.StartNew(() => p.SomeLongOperation();var arr = tasks.ToArray();秒表sw = Stopwatch.StartNew ();Task.WaitAll(arr);Console.WriteLine(“任务等待所有结果:”+ sw.Elapsed);sw.Stop();sw = Stopwatch.StartNew();Parallel.Invoke(() => p.SomeLongOperation(),() => p.SomeLongOperation());Console.WriteLine(“并行调用结果:”+ sw.Elapsed);sw.Stop();Console.ReadKey();}

下面是我的处理结果:

编辑:

将代码更改为如下形式:

    Program p = new Program();
    Task[] tasks = new Task[2];

    Stopwatch sw = Stopwatch.StartNew();
    tasks[0] = Task.Factory.StartNew(() => p.SomeLongOperation());
    tasks[1] = Task.Factory.StartNew(() => p.SomeLongOperation());

    Task.WaitAll(tasks);
    Console.WriteLine("Task wait all results: " + sw.Elapsed);
    sw.Stop();

    sw = Stopwatch.StartNew();
    Parallel.Invoke(() => p.SomeLongOperation(), () => p.SomeLongOperation());
    Console.WriteLine("Parallel invoke results: " + sw.Elapsed);
    sw.Stop();

我的新结果:

EDIT 2:当我将代码替换为Parallel.Invoke是第一个,Task.WaitAll是第二个时,情况发生了根本的变化。现在并行速度变慢了。这让我想到我估计的不正确之处。我更改了代码,如下所示:

Program p = new Program();
Task[] tasks = new Task[2];

Stopwatch sw = null;
for (int i = 0; i < 10; i++)
{
    sw = Stopwatch.StartNew();
    Parallel.Invoke(() => p.SomeLongOperation(), () => p.SomeLongOperation());
    string res = sw.Elapsed.ToString();
    Console.WriteLine("Parallel invoke results: " + res);
    sw.Stop();
}

for (int i = 0; i < 10; i++)
{
    sw = Stopwatch.StartNew();
    tasks[0] = Task.Factory.StartNew(() => p.SomeLongOperation());
    tasks[1] = Task.Factory.StartNew(() => p.SomeLongOperation());
    Task.WaitAll(tasks);
    string res2 = sw.Elapsed.ToString();
    Console.WriteLine("Task wait all results: " + res2);
    sw.Stop();
}

这是我的新结果:

现在我可以建议这个实验变得更加清晰。结果几乎是一样的。有时并行,有时任务更快。现在我的问题是:

1.我应该在哪里使用任务,在哪里并行?

2.与并行相比,使用任务有什么好处?

3.任务仅仅是ThreadPool.QueueUserWorkItem方法的包装吗?

欢迎任何可以澄清这些问题的有用信息。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-19 18:38:45

MSDN编辑this article的截止日期

并行和任务都是ThreadPool的包装器。并行调用也会等待,直到所有任务都完成。

与您的问题相关:

使用任务、并行或ThreadPool取决于执行并行任务所需的控制粒度。我个人已经习惯了Task.Factory.StartNew(),但这只是我个人的观点。ThreadPool.QueueUserWorkItem()也是如此

附加信息:由于内部初始化,第一次调用Parallel.Invoke()和Task.Factory.StartNew()可能会较慢。

票数 10
EN

Stack Overflow用户

发布于 2016-10-04 02:22:30

如果你启动了非泛型任务(即“不带返回值的空任务”)并立即对它们执行Wait,那么可以使用Parallel.Invoke。你的意图对读者来说一目了然。

在以下情况下使用任务:

如果您想要更多选项或控件<>H218>< ParallelOptions

  • basically,><>H218><>F219>,请不要使用ParallelOptions
    • basically,如果您想要更多选项或控件< CancellationToken >H218

    ,请不要等待<

  • >H218

如果您想要更多选项或控件<>H218>,您需要为名为TaskCreationOptions的方法提供参数如果您需要更多选项或控件,请不要使用CancellationTokenTaskScheduler

是的,你可以绕过其中的一些,例如Parallel.Invoke(() => p.OpWithToken(CancellationToken),但这会混淆你的意图。Parallel.Invoke是用尽可能多的CPU来做大量的工作。它完成了,它不会死锁,你提前知道这一点。

尽管你的测试很糟糕。危险信号是,您的长期操作是等待3000毫秒,而您的测试所需时间不到十分之一毫秒。

Task.Factory.StartNew(() => p.SomeLongOperation());

StartNew获取一个Action,并在一个新的main Task中执行它。操作() => SomeLongOperation()将创建一个子任务 Task。该子任务创建(未完成)后,对SomeLongOperation()的调用返回,操作完成。因此,main Task已经在十分之一毫秒后完成,而您没有引用的两个子任务仍在后台运行。并行路径还创建了两个子任务,它根本不跟踪它们,然后返回。

正确的方法应该是tasks[0] = p.SomeLongOperation();,它将一个正在运行的任务分配给数组。然后,WaitAll检查此任务的完成情况。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16101811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档