DiamonDogX

I have a task that takes several seconds to complete (tries to establish a connection with someone). Right now it is done on the UI thread when I press a button. I am wanting to popup a window with an indeterminate progress bar or something that comes up when I press the "Connect" button and closes when the task "completes". Presumably this has to be in a different thread so I am wondering what the best approach is. Is this a case for Dispatcher.BeginInvoke Normal C# threads Thanks.


Re: Windows Presentation Foundation (WPF) Threading and poping up a window with progress bar

Kayakyakr

Take a look at the "BackgroundWorker" class. I think it will have what you need :-)




Re: Windows Presentation Foundation (WPF) Threading and poping up a window with progress bar

DiamonDogX

The problem I run into is that I want a background thread yes.... but there's a UIElement (a dialog window in my case) that I want to show on the background thread... but that has to execute on the UI thread.... hmm..





Re: Windows Presentation Foundation (WPF) Threading and poping up a window with progress bar

Patrick Sears

Ok, so simply show the element on the UI thread and then kick off the background worker. When you receive progress events, update the element.





Re: Windows Presentation Foundation (WPF) Threading and poping up a window with progress bar

Chango V. - MSFT

As Patrick suggests, the most common pattern is to use a background thread to do the expensive work and switch to the UI thread just to update progress. In WPF, Dispatcher.BeginInvoke() is the easiest way to do this kind of thread switching. You can access the Dispatcher property of any element (UIElement/DispatcherObject) from the UI thread to get the right Dispatcher object for that thread.






Re: Windows Presentation Foundation (WPF) Threading and poping up a window with progress bar

Scott Grosch

Create a new Window object that contains your ProgressBar and whatever other UI you might want to show. In the code-behind you create a private BackgroundWorker element. Then, create an event handler like this:

Code Block

private void Window_Loaded(object sender, RoutedEventArgs e) {

this.worker = new BackgroundWorker {

WorkerReportsProgress = true

};

this.worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);

this.worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

this.worker.DoWork += new DoWorkEventHandler(worker_DoWork);

this.worker.RunWorkerAsync();

}

The worker_RunWorkerCompleted will probably just set DialogResult=true to close the window, but you could do other stuff.

Your worker_DoWork() routine is where you handle your connection (i.e. the long-running task). When you want to update your progress bar, just call this.worker.ReportProgress(percentProgress, userState). When you call that routine, it'll run your worker_ProgressChanged event.

While the first arg is percentProgress, it's really just an int. So I like to use it as a flag. If the "percent" is set to 1, then I'm telling my progress bar what the maximum value can be via the value of userState, and if it's 2, then I'm incrementing the value of the progress bar by 1. You could also do things like say 3 means that userState will be an int representing how much to increase the value by. So your update would look like this:

Code Block

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {

if (e.ProgressPercentage == 1) {

// We're specifying the maximum value for the ProgressBar

this.ProgressBar.Maximum = (int)e.UserState;

} else if (e.ProgressPercentage == 2)

// We just want to increment by one tick

this.ProgressBar.Value++;

else if (e.ProgressPercentage == 3) {

// We did a bunch of work at once, so increment by the specified value

this.ProgressBar.Value += (int)e.UserState;

}

}