Background thread 中修改 Silverlight 2 控制項的值

Silverlight 2 開始支援了多執行緒 (Multithreading) 能力,當自行建立的執行緒要修改控制項的屬性值時,由於使用者介面控制項是由主執行緒所掌控,若沒有適當處理,我們的程式碼會得到錯誤訊息 "呼叫執行緒無法存取此物件,因為此物件屬於另一個執行緒"。假設我產生一個新的執行緒,並且每隔 500 milliseconds 將數字累加 1 ,並送入名為 lstMain 的 ListBox 控制項中。

using System.Threading;

private Thread TaskThread;

private void button1_Click(object sender, RoutedEventArgs e)
{
    ThreadStart ThreadJob = new ThreadStart(this.DoTheJob);
    this.TaskThread = new Thread(ThreadJob);
    this.TaskThread.Start();
}

private void DoTheJob()
{
    for (int i = 0; i < 10; i++)
    {
        AddNumber(i);
        Thread.Sleep(500);
    }
}

Silverlight 2 對於處理不同執行緒修改控制項屬性值的作法,是與 WPF 一樣的。WPF 與 Silverlight 2 控制項都有一個 Dispatcher 屬性,不同執行緒要存取控制項之前,必須先如下程式碼

private delegate void DelgateAddNuber(int num);

private void AddNumber(int idx)
{
    if (this.lstMain.Dispatcher.CheckAccess())
        this.lstMain.Items.Add ("From another thread :"+idx.ToString());
    else
        this.lstMain.Dispatcher.BeginInvoke (new DelgateAddNuber(this.AddNumber), idx);

}

透過控制項 Dispatcher 物件的 CheckAccess 方法來確認,此一呼叫的執行緒是否與控制項自身為同一個執行緒? 倘若不是,執行緒就必須以 delegate 的方式藉由 Dispatcher 物件來修改屬性值,在 WPF 中 Dispatcher 物件同時提供了同步呼叫的 Invoke 方法與非同步呼叫的 BeginInvoke,但在 Silverlight 2 只有提供非同步的方法 BeginInvoke,並且 Silverlight 2 中,也沒有設定優先順序的參數 DispatcherPriority ,除此之外就都一樣了,附上個 Visual Studio 2008 與 Silverlight 3 Beta 1 的範例。

SilverlightThreadUI.zip