title: Showing a progress bar that updates while creating a lot of controls
body: <p>I've written a piece of code that creates a lot of controls and layouts them on a canvas to visualize a tree. Now this code can take a lot of time, especially since it sometimes has to query an external service to see if there are more child node.</p>
  
  <p>So I would like to show a progress bar while this code is executing. For other parts of my program I use a background worker that reports progress. However since I have to create controls that are later interact-able I don't see how to use a background worker or other threading solution here.</p>
  
  <p>Since this is WPF, I also can't call Application.DoEvents(). So my question is, how can I create a lot of controls while still being able to periodically update the visual part of the GUI?</p>
  
  <p>For my other code I use an Adorner that I layout over the busy piece of my app, I would prefer a solution where I can keep using that, I would also still prefer a solution using BackgroundWorker, but I'm pretty sure that is not possible.</p>
  
  <p>I've looked at other SO topics, but I can't find a good answer so far</p>
  
  <p><a href="https://stackoverflow.com/questions/1040770/creating-controls-in-a-non-ui-thread">Creating controls in a non-UI thread</a></p>
  
  <p><a href="https://stackoverflow.com/questions/6315277/creating-a-winform-on-the-main-thread-using-a-backgroundworker">Creating a WinForm on the main thread using a backgroundworker</a></p>
  
  <p>Edit:</p>
  
  <p>According to this MSDN article <a href="http://msdn.microsoft.com/en-us/magazine/cc163328.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/magazine/cc163328.aspx</a> the BackgroundWorker should automatically invoke asynchronously on the UI thread if required, but this is not the behaviour I'm seeing, since I still see a cross thread exception.</p>
  
  <p>Edit2: nvm, that's not totally true: <a href="https://stackoverflow.com/questions/1968222/backgroundworker-still-needs-to-call-invoke">BackgroundWorker still needs to call Invoke?</a></p>
  
  <p>Edit3: After some more reading and some tips, this is the solution I've come to. Anybody got any tips/hints?</p>
  
  <pre><code>        // Events for reporting progress
          public event WorkStarted OnWorkStarted;
          public event WorkStatusChanged OnWorkStatusChanged;
          public event WorkCompleted OnWorkCompleted;
  
  
          private BackgroundWorker worker;
          private delegate void GuiThreadWork(object state);
          private PopulatableControlFactory factory = new PopulatableControlFactory();
          public Canvas canvas;
  
          public void PerformLayout(TreeNode node)
          {
              OnWorkStarted(this, "Testing");
  
              worker = new BackgroundWorker();
              worker.WorkerReportsProgress = true;
              worker.DoWork += new DoWorkEventHandler(worker_DoWork);            
              worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
              worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
              worker.RunWorkerAsync(node);
          }
  
          private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
          {
              OnWorkCompleted(this);
          }
  
          private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
          {
              var workTuple = (Tuple&lt;GuiThreadWork, TreeNode&gt;)e.UserState;
              workTuple.First.Invoke(workTuple.Second); //Or begin invoke?
  
              if (OnWorkStatusChanged != null)
                  OnWorkStatusChanged(this, e.ProgressPercentage);
          }
  
          private void worker_DoWork(object sender, DoWorkEventArgs e)
          {
              TreeNode node = (TreeNode)e.Argument;            
              Thread.Sleep(1000);
              worker.ReportProgress(33, Tuple.New(Place(node), node));
              Thread.Sleep(1000);
              worker.ReportProgress(66, Tuple.New(Place(node.children[0]), node.children[0]));
              Thread.Sleep(1000);
              worker.ReportProgress(100, Tuple.New(Place(node.children[1]), node.children[1]));
          }
  
          private GuiThreadWork Place(TreeNode node)
          {            
              GuiThreadWork threadWork = delegate(object state)
              {
                  PopulatableControl control = factory.GetControl((TreeNode)state);
                  Canvas.SetLeft(control, 100);
                  Canvas.SetTop(control, 100);
                  canvas.Children.Add(control);
              };
  
              return threadWork;
          }   
  </code></pre>
  
  <p>In short: I use the progressChanged event of the background worker because this is always marshalled to the GUI thread. I pass it a tuple of a delegate and some state. This way I always create the control on the GUI thread and do all actions there, while still being flexible.</p>