2010-03-17 38 views
0

我一直在閱讀很多關於C#,WPF和Silverlight線程化的知識,但無法讓它工作。WPF中的易線程問題

我的主要問題是我有_load(_Initialized)操作,它有很多的對象創建,並且我有定時器在做不同的事情,這會導致程序的啓動時間非常緩慢,很明顯導致用戶界面掛起,這對於部署到很多用戶來說不是一件好事。

我的計時器更改標籤和文本框的值,但讓他們在另一個線程上這樣做顯然是不行的。

那麼有人可以給我一些關於如何實現我需要做的事情的例子嗎?

感謝

回答

1

訣竅是你的UI邏輯必須在UI線程上執行。有提供的方法使其比其他方法更容易,但使用它們可能會非常棘手。下面是我如何在過去所做的那樣:

首先,你必須要聲明一個代理,你可以喂到Dispatcher.Invoke方法:

private delegate void UIDelegate(); 

然後你就可以得到你的後臺工作的設置和調用它的方法的RunWorkerAsync:

BackgroundWorker loadWorker = new BackgroundWorker(); 
loadWorker.DoWork += new DoWorkEventHandler(loadWorker_DoWork); 
loadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loadWorker_RunWorkerCompleted); 
loadWorker.RunWorkerAsync(); 

然後,更新UI元素,你必須調用調度員:

private void changeStatusLabel(string status) 
{ 
    progressLabel.Dispatcher.Invoke(new UIDelegate(delegate 
    { 
     progressLabel.Content = status; 
    })); 
} 

這些都是從較大的方法中分離出來的,它們可能會進行一些優化。不過,這會給你一個從一開始的地方。

+0

感謝所有的信息,我試了一下,但loadWorker_DoWork()會怎麼樣呢?如果我有這樣的標籤:this.label.Content = getCurrentUsage()。ToString();我怎樣才能把它放在計時器中呢? –

+0

loadWorker_DoWork與您的計時器事件完全相同,並且是您需要使用Dispatcher.Invoke更新UI的位置。 –

+0

或者您可以使用BackgroundWorker的進度報告委託,該委派在UI線程上運行,用於此目的。 –

2

把你的工作到其他線程,並使用Dispatcher.Invoke元帥標籤和文本字段的設置返回到您的UI線程。

這就是說,如果可以的話,你也可以重構你的工作使用BackgroundWorker class。進度和完成事件已經封送回UI線程,因此在許多情況下更容易更新UI。

+0

Ahem。我確實認爲你的意思是Dispatcher.Invoke。如果您不同意,請回滾。 –

+2

@亨克:任何一個都可以使用。如果我只是設置標籤或其他類似的東西,我經常使用BeginInvoke而不是Invoke,因爲沒有理由等待操作完成。 - http://msdn.microsoft.com/en-us/library/ms591206.aspx –

+0

是的,我的錯誤。最近我看到幾個Delegate.BeginInvokes類似的答案。 –