首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待Parallel.For

等待Parallel.For
EN

Stack Overflow用户
提问于 2014-02-10 23:29:02
回答 3查看 12.2K关注 0票数 4

我知道不需要等待Parallel.For,但由于UI消息(WinForms消息泵)在Parallel.For期间正在处理,所以我希望等待Parallel.For完成。

Parallel.For封装在Task中,然后等待它是不是一个好主意?有没有更好的方法?

谢谢。

代码语言:javascript
复制
CancellationTokenSource token = new CancellationTokenSource();

const int len = 100;

double[] array = new double[len];

Task t = Task.Factory.StartNew(delegate {
   Parallel.For(0, len, delegate(int i, ParallelLoopState loopState) {

   array[i] += 1;

   });

try
{
   t.Wait(token.Token);
}
catch (OperationCanceledException e)
{
   rc = false;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-10 23:30:47

为什么不直接使用Task并调用Task.WaitAll()而不是Parallel.For

代码语言:javascript
复制
var t1 = Task.Run(() => {});
var t2 = Task.Run(() => {});

Task.WaitAll(t1, t2);
票数 5
EN

Stack Overflow用户

发布于 2014-02-10 23:31:30

如果你想等待一个Parallel.For()完成,你不需要在一个单独的任务中启动它!

Parallel.For()直到完成才会返回(即使它使用多个线程来完成这项工作)。

请注意,Parallel.For()返回一个ParallelLoopResult -它不返回任务或任何其他允许您等待它完成的内容,所以如果它在完成之前返回(如您所断言的),将无法知道它何时完成。

票数 4
EN

Stack Overflow用户

发布于 2014-02-11 09:36:47

Parallel.ForTask.Wait阻塞在UI线程上时,是什么让您如此确信WM_PAINT和其他Windows消息会被释放?

下面这个简单的例子证明你错了。在Parallel.For工作的整个15秒内,窗体都不会被重新绘制为红色。

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFroms_21681229
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            this.Shown += MainForm_Shown;
        }

        void MainForm_Shown(object sender, EventArgs e)
        {
            MessageBox.Show("Before");

            this.BackColor = Color.FromName("red");
            this.Invalidate();

            // the form is not getting red for another 15 seconds
            var array = new double[] { 1, 2, 3 };
            Parallel.For(0, array.Length, (i) =>
            {
                System.Threading.Thread.Sleep(5000);
                Debug.Print("data: " + array[i]);
            });

            MessageBox.Show("After");
        }
    }
}

这里介绍了如何在保持UI响应的同时并行运行任务:

代码语言:javascript
复制
async void MainForm_Shown(object sender, EventArgs e)
{
    MessageBox.Show("Before");

    this.BackColor = Color.FromName("red");
    this.Invalidate();

    // the form is not getting red for another 15 seconds
    var array = new double[] { 1, 2, 4 };

    var tasks = array.Select((n) => Task.Run(()=> 
    {
        Thread.Sleep(5000);
        Debug.Print("data: " + n);
    }));

    await Task.WhenAll(tasks);

    MessageBox.Show("After");
}

你可以做一些像await Task.Factory.StartNew(() => Parallel.For(...))这样的事情,但是这至少会比实际需要多使用一个线程。

要理解这里幕后发生的事情,您需要了解WinForms消息循环在Application.Run中是如何工作的,await如何将执行控制权交还给消息循环,然后在任务完成时通过WindowsFormsSynchronizationContext继续执行。async-await tag wiki可以提供帮助,它包含一些很棒的、必读的资源的链接。

如果您有兴趣了解消息泵在阻塞操作期间是如何工作的,请查看this answer

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

https://stackoverflow.com/questions/21681229

复制
相关文章

相似问题

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