我想實現一個Parallel.ForEach循環替換舊foreach循環,但我無法更新我的UI(我有顯示類似「X/Y文件處理」一個計數器)。我做了一個Parallel.For循環的例子來說明我的問題(標籤沒有被更新)。c#Parallel.For和UI更新?
using System;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
namespace FormThreadTest
{
public partial class Form1 : Form
{
private SynchronizationContext m_sync;
private System.Timers.Timer m_timer;
private int m_count;
public Form1()
{
InitializeComponent();
m_sync = SynchronizationContext.Current;
m_count = 0;
m_timer = new System.Timers.Timer();
m_timer.Interval = 1000;
m_timer.AutoReset = true;
m_timer.Elapsed += new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
m_timer.Start();
}
private void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Task.Factory.StartNew(() =>
{
m_sync.Post((o) =>
{
label1.Text = m_count.ToString();
Application.DoEvents();
}, null);
});
}
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Parallel.For(0, 25000000, delegate(int i)
{
m_count = i;
});
});
}
}
}
如果我改變按鈕單擊事件方法,並添加了Thread.Sleep(),它似乎給時間UI更新線程來完成其工作:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Parallel.For(0, 25000000, delegate(int i)
{
m_count = i;
Thread.Sleep(10);
});
});
}
是有沒有辦法避免睡眠,還是我需要在那裏?這似乎是我的用戶不會更新標籤,除非我這樣做?我覺得奇怪,因爲我可以將應用程序窗口(它不鎖) - 那麼,爲什麼慣於標籤更新了,我怎麼可以改變我的代碼,以更好地支持的Parallel.For(每個)和UI更新?
我一直尋找一個解決方案,但我不能似乎發現了什麼(或者我可能尋找錯誤的東西?)。
問候 西蒙
我對這個知之甚少,但是這可能與允許的線程數有關嗎?如果Parallel.For將他們全部拿走並且不留下任何事件來抓取,那麼這可以解釋行爲。但我對此並不確定,所以它真的只是一個瘋狂的猜測,希望能激發一個知道更多的人。 :) – Chris 2011-01-24 14:36:52
嘗試在設置標籤文本後放置Application.DoEvents()。這將讓其他線程(特別是UI線程)有機會重畫屏幕 – user2712361 2013-08-23 20:45:00