2013-12-21 66 views
1

我有應用程序在哪裏我使用後臺工作來開始一些序列。 有時需要更新GUI。BackgroundWorker,更新GUI,靜態方法

我有一些靜態類引用一些gui對象。 在我的邏輯中,我想從這個靜態類中調用方法,並帶有一些參數,然後分析它並更新GUI。 但我有「調用線程不能訪問此對象,因爲不同的線程擁有它。」異常。

設置變量在第一線:

public static void SetCardHand(ref CardHand ch) 
    { 
     cardHand = ch; 
    } 

方法從後臺工作線程調用:

private static void SetCoveredCardsPlayer0(int cardsNumber) 
    { 

     if (cardsNumber < 1) 
      cardHand.imgCard1.Source = null; 
     else 
      cardHand.imgCard1.Source = (ImageSource)WindowManager.Instance.CardsGUI.CardsDictionary["T1"]; 
    } 

如何讓這個方法改變GUI?

編輯

這不是一個窗口類。它像主持人一樣。

edit2

它是一款紙牌遊戲。我開始在後臺工作,我需要在每次交易後更新圖片來源(代表卡片)。

+0

根據您的應用程序設計,大綱爲backgroundworker.WorkerReportsProgress = true,並訂閱將在UI線程上運行的ProgressChanged。 – terrybozzio

+1

您必須詳細說明*您在哪裏調用SetCoveredCardsPlayer0。它應該來自Completed或ProgressChanged事件處理程序 - 如果不是,您會得到該異常。如果你在除Completed或ProgressChanged事件處理程序之外的其他地方進行調用,請參閱Grant在下面發佈的答案 –

回答

5

您必須在更新UI之前將控制權交還給主線程。 BackgroundWorker使這非常簡單。

  1. 當你創建BackgroundWorker,設置WorkerReportsProgress = true

  2. 訂閱ProgressChanged事件,並將用於更新UI的邏輯放入該事件中。

  3. 在您的DoWork事件中,當您要更新GUI時,請致電myBackgroundWorker.ReportProgress(0, someObject),其中「someObject」是您要採取行動的數據片段。在你的情況下,可能是ImageSource你分配給cardHand.imgCard1.Source

  4. ReportProgress事件中,您可以通過e.UserState訪問您傳遞的對象。在使用之前,您需要將其重新轉換回ImageSource

你可以把你的if (cardsNumber < 1)邏輯DoWork事件中,但是當你想將Source設置爲ImageSource(或null),你要的是值傳遞給ProgressChanged事件實際更新UI元素。

+0

這非常好,但我需要幾種不同類型的更新。 怎麼辦? – user1736332

+0

@ user1736332如果在線程運行時不得不在不同的時間用不同的數據更新多個控件,則必須以某種方式分離邏輯。您的'DoWork'事件可以在需要時將數據發送到'ProgressChanged'事件,然後您可以在'ProgressChanged'中擁有邏輯來測試它收到的數據並根據這些數據更新正確的控制。或者您可以等到全部完成DoWork事件並將所有數據傳遞給RunWorkerCompleted事件(使用Tuple或自定義類),並從此處更新所有UI組件。 –