的一般規則是:永遠不做阻塞UI線程
在Windows(和Windows CE爲好)的UI具有異步特性上。這意味着大多數API調用不一定會立即執行它們應該執行的任何操作。相反,它們生成一系列事件,這些事件放入事件隊列中,之後由事件泵檢索,實質上,這是一個在UI線程上運行的無限循環,逐個從隊列中挑選事件並處理它們。
從上面的結論可以得出結論,如果你在請求某個動作(即在你的情況下顯示窗口)之後繼續在UI線程上做很長的事情,事件泵將不能繼續進行拾取事件(因爲你還沒有控制它),因此,你的請求的行動無法完成。
一般方法如下:如果您必須執行復雜的數據轉換/加載/準備/任何,請在單獨的線程上執行它,然後使用Control.BeginInvoke將委託注入UI線程,然後觸摸從該委託內部實際的UI控件。
儘管您對多線程帶來的「複雜性」非常不理智,但很少有人會害怕。這裏有一個小例子來說明這一點:
public void ShowUI()
{
theForm = new MyForm();
theForm.Show();
// BeginInvoke() will take a new thread from the thread pool
// and invoke our delegate on that thread
new Action(PrepareData).BeginInvoke(null,null);
}
public void PrepareData()
{
// Prepare your data, do complex computation, etc.
// Control.BeginInvoke will put our delegate on the UI event queue
// to be retrieved and executed on the UI thread
theForm.BeginInvoke(new Action(PutDataInTheForm));
}
public void PutDataInTheForm()
{
theForm.textBox1.Text = "data is ready!";
}
雖然你可能有其他解決辦法玩,一般的想法始終保持不變:如果你做任何事情,在UI線程上長時間,你的用戶界面將「凍結」。當你在屏幕上添加新的UI元素時,它甚至不會重繪,因爲重畫也是一個異步過程。
因此,您必須在單獨的線程上完成所有複雜和長期的工作,並且只做簡單,小巧,保證在UI線程上運行快速的事情。沒有其他選擇,真的。
希望這會有所幫助。
as rediculous as this is,Application.DoEvents()靜態方法解決了問題,而不必使用任何額外的線程。我知道我不是「做正確的事情「並可能導致UI凍結等,但這對於我們所需要的就足夠了。 – 2010-01-20 17:19:04