2012-08-27 58 views
2

我有兩個線程。在另一個線程中創建更新控件?

線程1:WPF線程。顯示包含所有信息的窗口。
線程2:不斷循環,接收信息&更新線程1中的Window。

我有以下接口。

IModuleWindow 
{ 
    void AddModule(IModule module); 
    void RemoveModule(IModule module); 
} 

IModule 
{ 
    UserControl GetSmallScreen(); 
    UserControl GetBigScreen(); 
} 

IModuleWindow通過WPF窗口在線程1個
IModule的由對象執行實現,被實例化在線程2,然後發送到線程1

欲添加用戶控件在IModule到線程1中的Window對象,並顯示它們。 IModule對象在線程2中不斷更新,他們必須更改文本。

基本上的想法是,這個程序應該顯示線程2中的對象的狀態,它會不斷更新。

在WPF中完成此操作的最佳方法是什麼?

+0

您是否試圖顯示控件,創建在另一個線程,在窗口中創建主WPF線程? – Dennis

+0

能夠使用另一個線程創建的控件會很好,這就是我想要的。 – ProgrammerAtWork

回答

2

IMO最好的主意是用BackgroundWorker,用方法很方便的ReportProgress方法和ProgressChanged事件。

ProgressChanged事件在GUI線程中引發,因此您可以直接對GUI執行更新。這裏是你的代碼看起來應該像:

// initialize the worker 
BackgroundWorker backgroundWorker1 = new BackgroundWorker(); 
backgroundWorker1.WorkerReportsProgress = true; 
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged); 
backgroundWorker1.RunWorkerAsync(); 


// thread 2 (BackgroundWorker) 
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // main loop 
    while(true) 
    { 
     // time-consuming work 
     // raise the event; use the state object to pass any information you need 
     ReportProgress(0, state); 
    } 
} 

// this code will run on the GUI thread 
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // get your state back 
    object state = e.UserState; 
    // update GUI with state 
} 
+0

我認爲這確實是我需要的!謝謝。 – ProgrammerAtWork

+0

對不起,但Backgroundworker如何添加在另一個線程創建的UserControl?我無法完全控制用戶控件的內容將會在哪個控件中更新。 – ProgrammerAtWork

+0

@ProgrammerAtWork:你爲什麼不在GUI線程上創建這些控件,將它們傳遞給後臺工作者,更改它們,然後在GUI線程上更新它們?或者你在使用一些第三方代碼? – Tudor

1

It helped我很瞭解我必須做什麼。

的情況必須是這樣的:

ObservableCollection images = new ObservableCollection(); 
TaskFactory tFactory = new TaskFactory(); 

tFactory.StartNew(() => 
{ 
    for (int i = 0; i < 50; i++) 
    { 
    //GET IMAGE Path FROM SERVER 
    System.Windows.Application.Current.Dispatcher 
      .BeginInvoke((Action)delegate() 
      { 
      // UPDATE PROGRESS BAR IN UI 
      }); 

    images.Add((""); 
    }  
    }).ContinueWith(t => 
    { 
     if (t.IsFaulted) 
     { 
      // EXCEPTION IF THREAD IS FAULT 
      throw t.Exception; 
     } 
     System.Windows.Application.Current.Dispatcher 
     .BeginInvoke((Action)delegate() 
     { 
      //PROCESS IMAGES AND DISPLAY 
     }); 
    }); 

必須使用System.Windows.Application.Current.Dispatcher.BeginInvoke()在WPF UI更新。

+0

這是我見過的TPL使用最糟糕的例子之一。看到這個:http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx和http://msdn.microsoft.com/en-us/library/system.threading.tasks .task.exception。 – Dennis

1

這將是很好能夠使用在另一個線程創建的控件, 這就是我想要的理想

簡短的回答:算了吧。

UI控件只屬於單個UI線程。你可以在這裏做的最好的,是在主線程中創建控件,在後臺線程中準備數據,並且再次在主(UI)線程中更新控件的屬性。

對於數據準備,我建議使用TPL