views:

454

answers:

3

good evening!

currently i'm developing a wpf-client for some rest-service. the communcation with the rest-service is no problem and is done in an extra assembly (communcation-interface).

basically:
i have a somehow "search"-button which executes a method. this method communicates with the service, updates some textboxes and a progress-bar (to give the user some graphic info, how far we are ...). unfortunaly the server, which hosts the service is a bit lame, causing some severe response-time (about 4 secs). this, on the other hand, causes my wpf-application to wait, which ends up in: going black, and titeling "not responding" ...

i've already tried to put this execution in another thread, but ... it's logical that i won't get any access to the controls of my wpf-window ...

atm i'm really helpless ... can anyone give me some handeling-routine or a solution?

+3  A: 

Your UI thread is busy waiting on a response from the web service, and isn't available to paint the screen. One good option, is push the service request off to another, non-UI thread. Look into BackgroundWorker, which was designed specifically to make this easy. It handles marshalling of cross-thread calls from non-UI to UI threads.

Roughly:

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync(arg);
...

static void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker)sender;
    int arg = (int)e.Argument;
    e.Result = CallWebService(arg, e);
}

static void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Increment();
}

static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    label.Text = "Done: " + e.Result.ToString();
}
Michael Petrotta
this is basically what i tried, but i'm getting "The calling thread cannot access this object because a different thread owns it."
Andreas Niedermair
Code? Also, make sure you *don't* touch your UI from the doWork event handler.
Michael Petrotta
...or anything called by it (run on the same, non-UI thread).
Michael Petrotta
and so i did ... thank you for your solution, but i like the dispatcher-variant better!
Andreas Niedermair
+4  A: 

This video shows how to create an asynchronous progress bar using WPF and the Dispatcher.BeginInvoke method. It's a nice gentle introduction to a simple solution for basic cross threading issues in WPF.

Steve Willcock
the dispatcher-variant is the nicest one ... thank you sooo much!
Andreas Niedermair
+1  A: 

To access your controls from a second thread use Dispatcher.BeginInvoke:

Dispatcher.BeginInvoke(new Action(() =>
    {
        // Update your controls here.
    }), null);

Or you can look into using BackgroundWorker.

w4g3n3r