2009-11-11 60 views
0

我有一個Windows窗體(C#)項目,其中有多個組合框/列表框等​​等,當窗體加載時填充。當窗體加載時延遲加載組合框

的問題是,組合框/列表框的加載緩慢,因爲當窗體試圖顯示整個窗體不顯示,直到所有的控制都被填充裝載完成。這在某些情況下可能是20+秒。

如果有一個Form_finished_loaded類型的事件我可以把我的代碼放在那裏,但是我找不到在完成繪製基本控件之後觸發的事件。

雖然我有一個要求 - 加載必須在主線程中完成(因爲我從非線程友好的COM應用程序中獲取項目)。

我發現了一個潛在的解決方案,但也許有更好的方法? 我可以在創建表單時創建一個System.Timer.Timer,並在大約1秒鐘後調用第一個Tick,然後從該tick中填充列表。這使得表格有足夠的時間在開始填充列表之前顯示。

有沒有人有任何其他技巧如何延遲加載的控制?

回答

6

存在Shown event「只要首次顯示錶單就會發生」。您也可以使用BeginUpdate and EndUpdate函數更快地填充組合框。

+1

+1爲BeginUpdate/EndUpdate提示。 – 2009-11-11 16:10:16

+0

是不是BeginUpdate,EndUpdate用於在將大量項目順序加載到控件中時掛起繪畫,而不是用於長時間運行的過程?顯示事件爲+1。 – 2009-11-11 16:46:56

+0

得到它的工作! 當添加巨大的集合時,BeginUpdate/EndUpdate產生了巨大的差異。高達10倍的改進。 – 2009-11-11 22:40:55

0

您可以從調用COM組件的Web服務獲取數據嗎?

這樣,您可以在開始時顯示鎖定窗體上的空控件,使異步調用獲取數據,並在返回時填充相應的組合,並且一旦所有組合都加載完畢,就可以解鎖窗體用戶使用。

0

您可以聽取VisibleChanged事件,並且您首次將您的初始化代碼設置爲真值。

1

它有一定的氣味的解決方法,但這種方法應該滿足您的需求:

private bool _hasInitialized = false; 
private void Form1_Shown(object sender, EventArgs e) 
{  
    if (!_hasInitialized) 
    { 
     ThreadPool.QueueUserWorkItem(state => 
     { 
      Thread.Sleep(200); // brief sleep to allow the main thread 
           // to paint the form nicely 
      this.Invoke((Action)delegate { LoadData(); });  
     }); 
    } 
} 

private void LoadData() 
{ 
    // do the data loading 
    _hasInitialized = true; 
} 

它所做的是,如果它已經被初始化之前它反應顯示窗體時,支票和如果沒有,它會產生一個線程,它將在主線程上調用LoadData方法之前等待一小段時間。這將允許表單正確繪製。該samething或許可以通過簡單地調用this.Refresh()來實現,但我喜歡讓系統的想法決定如何做的工作。

我還是會嘗試將數據加載推到一個工作線程,主線程上調用回用於填充UI(如果它是與COM組件在所有可能的)。

0

是不是FormShown你正在尋找的事件?

+0

但是,UI線程在控件加載時仍會阻塞,導致應用程序無響應,對吧? – 2009-11-11 16:03:23

+0

打算編輯我​​的帖子以獲取更多詳細信息:)... 是的,Fredrik提出的建議(穿線)。我只是在開始線程之前用Application.DoEvents()替換Thread.Sleep()。 – 2009-11-11 16:06:01

0

當你說你不能使用,因爲COM的後臺線程你是什麼意思?我在我的應用程序中使用了許多COM組件,並在後臺線程上運行它們。

如果您創建一個新的線程作爲STAThread你也許可以加載在一個非UI線程組合框/列表框。 IIRC ThreadPool將工作線程分配爲MTAThread,因此您需要實際手動創建線程而不是使用ThreadPool.QueueUserWorkItem。