Drewmate
Drewmate

Reputation: 2159

Callback to update GUI after asynchronous ServiceStack web service call

I need to refresh a ListBox in my GUI once the asynchronous call to a web service has successfully returned. It is not so simple as dumping the results of the web service call in to an ObservableCollection since the results are actually put in to an indexed Dictionary and only the top 1000 results are displayed in the ListBox at any given time.

I have code to pick out the top 1000 results, and to refresh the ListBox display, I just need to figure out some way to call it once the result has returned succesfully.

this.client.GetAsync<RepositoryResponse>(string.Format
    ("/repository?Dto={0}", reader.Dto.ToJson()),
    r => ReadSuccessCallback(r),
    (r, x) => ReadErrorCallback(r, x));

This code is executed in a different dialog box than the window where the GUI update is made. I call this asynchronous get as I am closing the one dialog box, and hope to refresh the ListBox in the original window. I tried passing an Action object to be executed in the ReadSuccessCallback method, and it executes correctly, but gives me an error saying that the Items collection behind the ListBox belongs to a different thread, and can not be changed.

How can I get a new chunk of 1000 items (and refresh the display of the ListBox) only after the GetAsync has succesfully returned? Is there any way to make sure that the ReadSuccessCallback is executed in the same thread as my GUI is running in?

Upvotes: 2

Views: 1002

Answers (2)

mythz
mythz

Reputation: 143374

If you want to update UI controls you should invoke the callback on the UI thread. Here's a good article showing different ways to do this using the WPF Dispatcher.

So one of the ways would be to do something like:

this.client.GetAsync<RepositoryResponse>(string.Format
("/repository?Dto={0}", reader.Dto.ToJson()),
r => {
    myListBox.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal, () => {
           //populate results int myListBox
        }); 
},
(r, x) => ReadErrorCallback(r, x));

Upvotes: 1

ΩmegaMan
ΩmegaMan

Reputation: 31686

This is kind of old school, but it should work. Place the operation in question into a background worker DoWork event, with the client call you showed changed to a synchronous one, since its now in its own thread, pass the data of the result to the RunWorkerCompleted event and then process what is needed for the listbox at that point safely for the GUI thread.

Upvotes: 1

Related Questions