问题描述
我在使用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 onvar 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的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!