C# 调用以并行化foreach时出现问题

C# 调用以并行化foreach时出现问题,c#,parallel-processing,C#,Parallel Processing,我在使用System.Threading.Tasks.Parallel.ForEach时遇到问题。要更新每个progressBar的主体。 但调用方法有时会冻结 我将代码附加到表单上,该表单是prograssbar和Buton private void button1_Click(object sender, EventArgs e) { DateTime start = DateTime.Now; pforeach(); Text = (DateTime.Now - s

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

我将代码附加到表单上,该表单是prograssbar和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;
}
private void按钮1\u单击(对象发送者,事件参数e)
{
DateTime start=DateTime.Now;
pforeach();
Text=(DateTime.Now-start).ToString();
}
私有void pforeach()
{
int[]intArray=新int[60];
int totalcount=intArray.Length;
对象lck=新对象();
系统。线程。任务。并行。ForEach(intArray,
() => 0,
(x,循环,计数)=>
{
int值=0;
系统线程线程睡眠(100);
计数++;
值=(int)(100f/(浮点)总计数*(浮点)计数);
设置(值);
返回计数;
},
(x) =>
{
});
}
私有无效集(int i)
{
if(this.invokererequired)
{
var result=Invoke(新动作(集合),i);
}
其他的
progressBar1.值=i;
}
有时它会顺利通过,但通常会冻结
var result=Invoke(新动作(集合),i)
。 试着在这个问题上踢我一脚


谢谢。

我正在研究我是如何做到这一点的,这一变化可能会帮助您:

在我的构造函数中,我有这样一行:

TaskScheduler uiScheduler=TaskScheduler.FromCurrentSynchronizationContext()

然后我会这样做:

    private void changeProgressBar()
    {
        (new Task(() =>
        {
            mainProgressBar.Value++;
            mainProgressTextField.Text = mainProgressBar.Value + " of " + mainProgressBar.Maximum;
        })).Start(uiScheduler);
    }
这样就不需要使用Invoke,如果您使用
Task
方法,那么它可能会解决您的问题


我想这些都在
System.Threading.Tasks中

您的问题是
调用
(以及将
任务
排队到UI
任务调度程序
)都需要UI线程处理其消息循环。然而,事实并非如此。它仍在等待
Parallel.ForEach
循环完成。这就是为什么会出现僵局

如果希望运行
Parallel.ForEach
而不阻塞UI线程,请将其包装到
任务中,如下所示:

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; 
} 
private任务调度器ui;
私有无效按钮1\u单击(对象发送者,事件参数e)
{
ui=TaskScheduler.FromCurrentSynchronizationContext();
DateTime start=DateTime.Now;
Task.Factory.StartNew(pforeach)
.ContinueWith(任务=>
{
task.Wait();//确保将错误传播到UI线程。
Text=(DateTime.Now-start).ToString();
},用户界面);
} 
私有void pforeach()
{ 
int[]intArray=新int[60];
int totalcount=intArray.Length;
对象lck=新对象();
系统。线程。任务。并行。ForEach(intArray,
() => 0, 
(x,循环,计数)=>
{ 
int值=0;
系统线程线程睡眠(100);
计数++;
值=(int)(100f/(浮点)总计数*(浮点)计数);
Task.Factory.StartNew(
()=>设置(值),
取消令牌。无,
任务创建选项。无,
ui)等待();
返回计数;
}, 
(x) =>
{ 
}); 
} 
私有无效集(int i)
{ 
progressBar1.值=i;
}