Tim Huffam

Dotting the I and crossing the T of I.T.

  Home  |   Contact  |   Syndication    |   Login
  140 Posts | 0 Stories | 1468 Comments | 659 Trackbacks

News

Archives

Post Categories

Interesting Blogs/Links

To update the UI with values returned from an asynchronous WCF/web service call you need to make sure the coding updating the UI is running on the UI thread.  Depending on how you've performed the async remote service call, often this is done on another thread - so when the handler executes upon completion of the call it is not on the UI thread and causes a threading exception.

Within winforms, the solution is to use the Invoke() method eg the following method would be on your form or user control and could be safely called from the async service call handler:

public void UpdateCustomerName()
{
 
if (this.InvokeRequired)
  {
   
this.Invoke(new EventHandler(delegate
     
{textBox1.Text = presenter.Customer.Name;}));
  }
 
else
 
{
    textBox1.Text = presenter.Customer.Name;
  }
}

If you're using something like the MVP pattern (in winforms) then you could make your presenter base class provide some generic handling for it with these 2 members:

protected delegate void UIDeligate();/// <summary>
/// Invokes the specified method in the UI thread. This is useful for executing view methods, that update the UI, from an asynchronous callback handler in the presenter.
/// Eg: <code>OnUIThread(new Presenter&lt;ITestView&gt;.UIDeligate(View.BindCustomers));</code>
/// </summary>
///
/// <example>
/// The folling code executes the view method BindCustomrs() in the UI thread.
/// OnUIThread(new Presenter&lt;ITestView&gt;.UIDeligate(View.BindCustomers));
/// </example>
/// <param name="method">Method to invoke.</param>
protected void OnUIThread(UIDeligate method)
{
 
if (disposed) return;
 
Control control = View as Control;
 
if ((control != null) && (control.Created))
    control.Invoke(method);
 
else
   
method.DynamicInvoke();
}

These allow your presenter to handle the thread synchronization for you (as it would be the one handling the the callback processing).  In this case your UI method, in your form or usercontrol, would look like this:

public void UpdateCustomerName()
{
    textBox1.Text = presenter.Customer.Name;
}

and the presenter implementation class would call it like this:

public void customerService_CustomerUpdate(object sender, EventArgs<Customer> e)
{
  customer = e.Data;

  // Previously we would have done: 
 
// View.UpdateCustomerName();
  // but now we do this:
  OnUIThread(new Presenter<ITestView>.UIDeligate(View.BindLivingExpenseRates));
}

So now the view does not need to care about any threading/async issues.

You could also use the <methodname>Async method and <methodname>Completed event in the generated WCF client proxy - as from what I've seen the <methodname>Completed event magically executes on the UI thread (have no idea how/why).  See this article for a good example.

HTH
Tim

 

posted on Tuesday, July 07, 2009 9:56 PM