更新另一个线程中创建的控件?

时间:2012-08-27 09:47:07

标签: c# .net wpf multithreading design-patterns

我有两个主题。

线程1:WPF线程。显示包含所有信息的窗口。
线程2:不断循环,接收信息&更新线程1中的窗口。

我有以下界面。

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

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

IModuleWindow由线程1中的WPF窗口实现 IModule由一个对象实现,在线程2中实例化,然后发送到线程1。

我想将IModule中的UserControls添加到线程1中的Window对象,并显示它们。 IModule对象在线程2中不断更新,他们必须更改文本。

基本上这个想法是这个程序应该显示线程2中的对象状态,它会不断更新。

在WPF中实现此目的的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

IMO最好的办法是使用BackgroundWorker,使用非常方便的ReportProgress方法和ProgressChanged事件。

在GUI线程上引发ProgressChanged事件,因此您可以直接对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
}

答案 1 :(得分: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。

答案 2 :(得分:1)

  

能够使用在另一个线程上创建的控件会很高兴,   这就是我理想的想法

答案简短:忘了。

UI控件仅属于单个UI线程。你可以做的最好的事情是在主线程中创建控件,在后台线程中准备数据,并再次在主(UI)线程中更新控件的属性。

对于数据准备,我建议使用TPL