我開始嘗試向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 - 你能否詳細說明或舉個例子?今天之前我從來沒有用過多線程做過什麼。 –