我开始尝试向Windows窗体添加进度条,该窗体更新在Parallel.Foreach循环内运行的代码的进度。为了做到这一点,UI线程必须可用来更新进度条。我使用了一个Task来运行Parallel.Foreach循环以允许UI线程更新进度条。在.NET 4.0中使用Parallel.Foreach任务
在Parallel.Foreach循环内完成的工作相当密集。使用Task运行程序的可执行文件(不在Visual Studio中进行调试)后,程序无响应。如果我没有任务运行我的程序,情况并非如此。我注意到两个实例之间的主要区别在于,程序在没有任务的情况下运行需要约80%的CPU,而在运行任务时约为5%。
private void btnGenerate_Click(object sender, EventArgs e)
{
var list = GenerateList();
int value = 0;
var progressLock = new object();
progressBar1.Maximum = list.Count();
Task t = new Task(() => Parallel.ForEach (list, item =>
{
DoWork();
lock (progressLock)
{
value += 1;
}
}));
t.Start();
while (!t.IsCompleted)
{
progressBar1.Value = value;
Thread.Sleep (100);
}
}
边注:我知道
Interlocked.Increment(ref int___);
工作到位的锁。它被认为更有效率吗?
我的问题是三倍:
1)为什么会与工作程序无响应时的负荷要少得多?
2.)使用Task来运行Parallel.Foreach是否将Parallel.Foreach的线程池限制为仅运行任务的线程?
3.)有没有办法让UI线程响应,而不是在没有使用取消标记的情况下睡1秒的时间?
我很感激任何帮助或想法,我花了相当多的时间研究这一点。如果我违反了任何发布格式或规则,我也很抱歉。我试图坚持他们,但可能错过了一些东西。
等待在UI线程上循环完成的任务就像在UI线程上执行它(稍微差一点)。看看'BackgroundWorker'或'async' – SimpleVar
如果'DoWork()'访问你的任何UI元素,它将导致死锁发生。 –
JohnathonSullinger - DoWork()不访问任何UI元素。 @Yorye Nathan - 你能否详细说明或举个例子?今天之前我从来没有用过多线程做过什么。 –