Ben Williams
Ben Williams

Reputation: 6167

Handling threading and web requests on Windows Phone 7

How can you make a background web request and then update the UI, but have all the code that does the web requesting/parsing in a separate class so you can use it in multiple places? I thought I could use the classes methods as event handlers for a BackgroundWorker class, like

APIHelper mHelper = new APIHelper("http://example.com?foo=bar");
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork +=new DoWorkEventHandler(mHelper.GetResponse);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(mHelper.HandleResponse);
bw.RunWorkerAsync();

where APIHelper has the method

public void GetResponse(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = (BackgroundWorker) sender;

    WebRequest request = HttpWebRequest.Create(this.URL);
    IAsyncResult result = (IAsyncResult)
                              request.BeginGetResponse(ResponseCallback, request);
}

but then I don't know how to access the worker thread from ResponseCallback and, anyway, HandleResponse gets called first (obviously). (I tried putting in result.AsyncWaitHandle.WaitOne(); but I get a NotSupportedException error.) Yet I can't work out how to make the web request call synchronously. I'm clearly trying to go about this the wrong way, but I have no idea what the right way is.


ETA:

My aim is to be able to go:

I can do the first two bits, and if I have the response, I can do the last bits, but I can't work out how to do the middle bit. Hopefully that made it clearer!

Upvotes: 1

Views: 520

Answers (3)

Mo Valipour
Mo Valipour

Reputation: 13486

It might be useful if you use a helper class that I have developed for WebDownload purposes during WP7 development.

I'm using it in 2-3 WP7 apps and no problem so far. Give it a go to see if it helps. You can get the class from the my blog linked bellow:

http://www.manorey.net/mohblog/?p=17#content

[NOTE] When working with this class you don't need to run anything in a background worker or new thread; it handles it all asynchronously.

Upvotes: 0

Matt Lacey
Matt Lacey

Reputation: 65564

I'd put all this logic in a viewmodel that the viewmodel of each page inherits from.
Have the pages bind to properties on the viewmodel (such as ShowLoading, etc.) which the model updates appropriately. i.e. before making the webrequest and in the callback.

As you won't be running the viewmodel code in the UI thread you also wouldn't need to run in a separate BackgroundWorker and you'll be able to access the properties of the viewmodel without issue.

Upvotes: 0

Luke Duddridge
Luke Duddridge

Reputation: 4347

It took me several tried before I found there is a Dispatcher.

During the BackgroundWorker's dowork and complete methods you can call:

this.Dispatcher.BeginInvoke(() =>
{
// UPDATE UI BITS
});

I think the Dispatcher is only available in the view. So I'm not sure if the methods can exist outside of the xaml.cs

Put whatever you want to update in your UI; when updating an ObservableCollection you must do the update of you items in the Dispatcher.BeginInvoke too

This link might be a good read too: http://www.windowsphonegeek.com/articles/All-about-Splash-Screens-in-WP7-ndash-Creating-animated-Splash-Screen

Update to assist notes

This is just a rough idea mind you...

bw.DoWork +=new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(Complete)

// At least I think the EA is DoWork....
public void DoWork(object sender, DoWorkEventArgs e)
{
        mHelper.GetResponse();
        this.Dispatcher.BeginInvoke(() =>
        {
              UIObject.Visibility Collapse.
        });

        // Wait and do work with response.
    });
}

public void Complete(object sender, RunWorkerCompleteEventArgs e)
{
        this.Dispatcher.BeginInvoke(() =>
        {
              UIObject.Visible ....
        });
}

Upvotes: 2

Related Questions