views:

1921

answers:

3

e.g. in Winforms I'd write...

// on UI Thread
    BackgroundWorker workerThread = new BackgroundWorker();
    workerThread.DoWork += new DoWorkEventHandler(LoadChildren);
    workerThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnLoadChildrenCompleted);
    while (workerThread.IsBusy)
    {
      Application.DoEvents();
    }

In WPF what is the equivalent of Application.DoEvents in Winforms?

I have a property called Children in my ViewModel class. A HierarchicalDataTemplate has been setup to read Items from the Children property.
A TreeView displays the nodes. When the user expands a node, the children of the node are generated from the results of this property

public Node Children
{
  get
  {
    // 1. time-consuming LINQ query to load children from a SQL DB
    // 2. return results
  } 
}

So I'd like to run 1. on a background thread and wait for it to complete before returning the results... keeping the UI responsive.

Googling led me to this page which has uses DispatcherFrames to simulate the above method. But this seems to be too much work.. which hints at 'Am I doing this right?'

+2  A: 

Calling DoEvents on the UI thread in a loop like this is not recommended practice in WinForms or WPF.

If your application can't continue until this thread has finished its work, then why is it on another thread?

If some parts of your application can continue, then disable those bits that can't and reenable them when your completion callback is called. Let the rest of the system get on with its stuff. No need for the loop with DoEvents in it, this is not good practice.

Take a look at the community content on MSDN.

This is a good article on DoEvents.

Sam Meldrum
To keep the UI Responsive. I dont want my UI hung, while the time consuming operation is in Progress. At the same time I want the Children to be loaded before returning the list of children.
Gishu
I still think that disabling the controls the user mustn't interact with while the child process is running on another thread and then re-enabling when your callback happens is the best way to keep your application responsive. DoEvents is a bad way to keep your application responsive.
Sam Meldrum
I'll update my question to give you a little more context...
Gishu
W.r.t. JFo's article My situation is "Have a whole bunch of UI to update, need to make the UI responsive whilst adding new items". One of the solutions listed is a Backgroundworker. Diff: If I dont wait for the list of children to be available before returning, data binding would blow up.
Gishu
+3  A: 

As I understand it, you've got this sort of flow:

  • Do some prep work (UI thread)
  • Do some background work (other thread)
  • Do some finishing work (UI thread)

You want to wait for the second bullet to finish before running the code in the third.

The easiest way to do that is make the second bullet's code call back into the UI thread (in the normal way) to trigger the third bullet to execute. If you really, really want to use local variables from the method, you could always use an anonymous method or lambda expression to create the delegate to pass to the background worker - but normally it would be cleaner to just have a "PostBackgroundWork" method or something like that.

EDIT: This wouldn't be nice for a property as you've shown in your edited question, but I'd refactor that as a request to fetch the children with a callback when it's completed. This avoids the whole mess of reentrancy, and makes it clearer what's actually going on.

Jon Skeet
Yes so I've replaced 1. with a Backgroundworker to do the heavy fetching on a different thread. Now while I wait for the results to be fetched, I need to wait (but allow UI events to be processed).. which is where I'm stuck..
Gishu
See my edit - the property shouldn't be implemented this way, basically. (Any property which needs to do work on a different thread is really overstepping its bounds anyway, IMO.) Make it a method which takes a callback to execute when the children have been fetched.
Jon Skeet
+1  A: 

In WPF what is the equivalent of Application.DoEvents in Winforms?

There is none built-in, but you can easily write your own. Indeed, WPF gives you more power around message processing than does Winforms. See my blog post on Dispatcher Frames here. It includes an example showing you how to simulate Application.DoEvents().

HTH, Kent

Kent Boogaart
Your solution (the blog) seems to be the same as the link at the end of my question. Or did I speed read again ?
Gishu
No, that's a different link. Please read my blog post - it contains a much terser implementation.
Kent Boogaart
Sorry.. ODed on links on this topic. http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/8c5f13f2-ac7a-412d-ae9e-64126aa8ace8/ is where i read about the one-line version.
Gishu