调用以并行化foreach的问题 [英] Problem with Invoke to parallelize foreach

查看:100
本文介绍了调用以并行化foreach的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用System.Threading.Tasks.Parallel.ForEach时遇到问题. foreach progressBar的主体要更新. 但是调用方法有时会冻结.

I have a problem with using System.Threading.Tasks.Parallel.ForEach. The body foreach progressBar want to update. But Invoke method sometimes freeze.

我将代码附加到prograssbar和Buton的表单上.

I attach the code to the form which is prograssbar and Buton.

private void button1_Click(object sender, EventArgs e)
{
    DateTime start = DateTime.Now;
    pforeach();
    Text = (DateTime.Now - start).ToString();
}


private void pforeach()
{
    int[] intArray = new int[60];
    int totalcount = intArray.Length;
    object lck = new object();
    System.Threading.Tasks.Parallel.ForEach<int, int>(intArray,
    () => 0,
    (x, loop, count) =>
    {
        int value = 0;
        System.Threading.Thread.Sleep(100);
        count++;
        value = (int)(100f / (float)totalcount * (float)count);

        Set(value);
        return count;
    },
    (x) =>
    {

    });
}

private void Set(int i)
{
    if (this.InvokeRequired)
    {
        var result = Invoke(new Action<int>(Set), i);
    }
    else
        progressBar1.Value = i;
}

有时它会顺利通过,但通常会冻结 var result = Invoke (new Action <int> (Set), i). 试着踢我这个问题.

Sometimes it passes without a problem, but usually it freeze on var result = Invoke (new Action <int> (Set), i). Try to kick me in the problem.

谢谢.

推荐答案

您的问题是Invoke(并且将Task排队到UI TaskScheduler)都需要UI线程来处理其消息循环.但是,事实并非如此.它仍在等待Parallel.ForEach循环完成.这就是为什么会出现死锁的原因.

Your problem is that Invoke (and queueing a Task to the UI TaskScheduler) both require the UI thread to be processing its message loop. However, it is not. It is still waiting for the Parallel.ForEach loop to complete. This is why you see a deadlock.

如果希望Parallel.ForEach在不阻止UI线程的情况下运行,请将其包装到Task中,如下所示:

If you want the Parallel.ForEach to run without blocking the UI thread, wrap it into a Task, as such:

private TaskScheduler ui;
private void button1_Click(object sender, EventArgs e) 
{
    ui = TaskScheduler.FromCurrentSynchronizationContext();
    DateTime start = DateTime.Now;
    Task.Factory.StartNew(pforeach)
        .ContinueWith(task =>
        {
            task.Wait(); // Ensure errors are propogated to the UI thread.
            Text = (DateTime.Now - start).ToString(); 
        }, ui);
} 

private void pforeach() 
{ 
    int[] intArray = new int[60]; 
    int totalcount = intArray.Length; 
    object lck = new object(); 
    System.Threading.Tasks.Parallel.ForEach<int, int>(intArray, 
    () => 0, 
    (x, loop, count) => 
    { 
        int value = 0; 
        System.Threading.Thread.Sleep(100); 
        count++; 
        value = (int)(100f / (float)totalcount * (float)count); 

        Task.Factory.StartNew(
            () => Set(value),
            CancellationToken.None,
            TaskCreationOptions.None,
            ui).Wait();
        return count; 
    }, 
    (x) => 
    { 

    }); 
} 

private void Set(int i) 
{ 
    progressBar1.Value = i; 
} 

这篇关于调用以并行化foreach的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆