【问题标题】:Parallel.Invoke() without waiting on execution to finishParallel.Invoke() 无需等待执行完成
【发布时间】:2014-01-29 20:27:47
【问题描述】:

请注意,我知道 Parallel.Invoke() 用于任务同步。我的问题是这样的:

有没有办法使用类似 Parallel.Invoke 的方式调用匿名方法,其中调用不会等待执行完成?

我认为并行执行(或并行调用)的全部意义在于不必等待任务完成。如果你想等待一段代码完成执行,而不是使用Parallel.Invoke,为什么不直接调用代码呢?我想我只是不明白 Parallel.Invoke 的意义。文档只是说什么它做了什么,但没有提到任何用例,这比直接调用代码更有用。

【问题讨论】:

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


    【解决方案1】:

    如果你想等待一段代码完成执行,而不是使用Parallel.Invoke,为什么不直接调用代码呢?

    通常你会打电话给Parallel.Invoke 处理多项工作。如果您以串行方式执行这些工作,则(可能)会比并行执行它们花费更长的时间。

    “并行执行”与“在后台执行”不同——您似乎在寻找后者,但这不是 Parallel.Invoke 的意义所在。

    如果您只想启动任务,请使用 Task.Run(或 .NET 4.5 之前的 Task.Factory.StartNew)。 Parallel.Invoke 专门用于并行执行一堆动作,然后等待这些并行动作完成。

    作为一个具体的例子,您可以通过分区来执行排序,然后并行地对枢轴的两侧进行递归排序。这样做会利用多个核心,但您通常仍希望等到整个排序完成后再继续。

    【讨论】:

    • 你说得对,我的印象是并行执行和后台执行是一样的。你能告诉我区别是什么以及它如何应用于 Parallel.Invoke 吗?或者向我指出可以帮助我理解差异的资源?
    • @Anshul:并行执行只是使用多个内核来完成一个目标。 可以以“即发即弃”的方式完成,但并非总是如此。请参阅我的编辑,了解在不将其设为后台任务的情况下并行化工作何时有用的具体示例。
    • 如果我有 2 个 Parallel.Invokes 在序列中,第二个不会等到第一个完成被调用吗?在这种情况下,您将如何使用 Parallel.Invoke 并行执行多段代码?
    • @Anshul Parallel.Invoke(action1,action2); 两个动作将并行运行,但 Parallel.Invoke 将等待它们完成。假设它们的执行时间是t1t2Parallel.Invoke 将等待 max(t1,t2)seconds。
    • @L.B 现在说得通了。我只是对应该做什么 Parallel.Invoke 产生了错误的想法。
    【解决方案2】:

    如果您不想等待完成,只需将您的 Parallel.Invoke 调用封装在 Task 中即可。

    Task.Factory.StartNew( () =>
        {
            Parallel.Invoke( <one or more actions> );
        } );
    

    【讨论】:

    • 如果我要做Task.Factory.StartNew(()=>{//dowhatever});而不是使用 Parallel.Invoke?既然你基本上是在开始一项新任务,它不会产生同样的效果吗?
    • 当然,不过,您需要为希望并行执行的每个操作启动一个新任务。
    • 明白。好像我误解了 Parallel.Invoke() 背后的原因。
    • 如果您只是想在后台线程上执行操作,请为该操作创建一个任务。 Parallel.Invoke 是如果您想“同时”执行多个操作
    • 然后在它们执行完成后同步
    【解决方案3】:

    你在寻找这样的东西吗?

    async Task ParallelInvokeAsync(Action[] actions)
    {
        var tasks = actions.Select(a => Task.Run(a));
        await Task.WhenAll(tasks);
    }
    

    后台执行:

    ParallelInvokeAsync(actions); 
    MessageBox.Show("I'm working");
    

    带阻塞的后台执行,非常类似于Parallel.Invoke:

    ParallelInvokeAsync(actions).Wait(); 
    MessageBox.Show("I'm dome working");
    

    【讨论】:

    • 我想这也可以。我只需要利用 TPL 并与当前执行行并行执行一段代码的东西。我的意思是当前的执行行不应该等待并行任务完成。 Task.Factor.StartNew(()=>{}) 满足这个要求。我主要想保持通话简洁。
    • @Anshul,你如何使用它取决于调用者。我更新了答案以说明它。理论上,Task.Factory.StartNew(() =&gt; Parallel.Invoke(actions)) 会比上面的ParallelInvokeAsync(actions) 多创建一个线程。
    猜你喜欢
    • 2014-08-09
    • 1970-01-01
    • 2016-02-21
    • 2015-09-16
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多