I’m having a big problem when calling a web service from my WPF application. The application/window locks until the process has completed. I’ve attempted to run this asynchronously but the problem still persists.
Currently, the web service call I’m making can last 45-60 seconds. It runs a process on the server to fetch a big chunk of data. As it take a little while I wanted to have a progress bar moving indeterminately for the user to see that the application hasn’t stalled or anything (you know how impatatient they get).
So:
private void btnSelect_Click(object sender, RoutedEventArgs e)
{
wDrawingList = new WindowDrawingList(systemManager);
AsyncMethodHandler caller = default(AsyncMethodHandler);
caller = new AsyncMethodHandler(setupDrawingList);
// open new thread with callback method
caller.BeginInvoke((Guid)((Button)sender).Tag, MyAsyncCallback, null);
}
Click a button and the app will create the form that the async stuff will be posted to and set up the async stuff calling the async method.
public bool setupDrawingList(Guid ID)
{
if (systemManager.set(ID))
{
wDrawingList.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
{
wDrawingList.ShowForm();
Hide();
}));
return true;
}
return false;
}
This is the async method. The showForm method contains the calls to setup the new form including the monster web service call
public void MyAsyncCallback(IAsyncResult ar)
{
// Because you passed your original delegate in the asyncState parameter of the Begin call, you can get it back here to complete the call.
MethodDelegate dlgt = (MethodDelegate)ar.AsyncState;
// Complete the call.
bool output = dlgt.EndInvoke(ar);
try
{
// Retrieve the delegate.
AsyncResult result = (AsyncResult)ar;
AsyncMethodHandler caller = (AsyncMethodHandler)result.AsyncDelegate;
// Because this method is running from secondary thread it can never access ui objects because they are created
// on the primary thread.
// Call EndInvoke to retrieve the results.
bool returnValue = caller.EndInvoke(ar);
// Still on secondary thread, must update ui on primary thread
UpdateUI(returnValue == true ? "Success" : "Failed");
}
catch (Exception ex)
{
string exMessage = null;
exMessage = "Error: " + ex.Message;
UpdateUI(exMessage);
}
}
public void UpdateUI(string outputValue)
{
// Get back to primary thread to update ui
UpdateUIHandler uiHandler = new UpdateUIHandler(UpdateUIIndicators);
string results = outputValue;
// Run new thread off Dispatched (primary thread)
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, uiHandler, results);
}
public void UpdateUIIndicators(string outputValue)
{
// update user interface controls from primary UI thread
sbi3.Content = "Processing Completed.";
}
Any help or theories are appreciated. I’m at a loss.
Thanks in advance
You are invoking the method onto the GUI thread using the dispatcher. This means that even though you started off on a background thread, you are switching straight back onto the GUI thread so the GUI will not be able to respond.
You need to let the main work happen on the background thread and then only use the dispatcher to switch to the GUI thread when you need to update the progress bar.