views:

1653

answers:

5

If you call a web service from Silverlight like this:

MyServiceClient serviceClient = new MyServiceClient();
void MyMethod()
{
  serviceClient.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(serviceClient_GetDataCompleted);
  serviceClient.GetDataAsync();

  // HOW DO I WAIT/JOIN HERE ON THE ASYNC CALL, RATHER THAN BEING FORCE TO LEAVE THIS METHOD?

}

I would rather wait/join with the asych service thread inside "MyMethod" rather than leaving "MyMethod" after calling "GetDataAsync", what is the best way to do this?

Thanks, Jeff

+1  A: 

To do this you would use a ManualResetEvent in your class (class level variable) and then wait on it.

void MyMethod()
{
  wait = new ManualResetEvent(false);
  // call your service
  wait.WaitOne();
  // finish working
}

and in your event handler code

void serviceClient_GetDataCompleted(...)
{
  // Set values you need from service
  wait.Set();
}
Bryant
A: 

You could also use a lambda and closure to get similar behavior:

serviceClient.GetDataCompleted += (s,e) =>
{
  // Your code here
};
serviceClient.GetDataAsync();
Shawn Wildermuth
+2  A: 

No you cannot do this way. You will end up in a deadlock. GetDataCompleted is called by the mainthreed. The same threed thait is waiting in WaitOne.

Henrik Lamm
A: 

If you had a base class provide the mechanics of building a WCF channel, it could then be used to build the BeginX / EndX methods for a async call.

public class ServiceFooCoordinator : CoordinatorBase<IServiceFoo>
{
    public IAsyncResult BeginMethodFoo ()
    {
        IAsyncResult ar = null;
        IServiceFoo channel = null;
        channel = _factory.GetChannel();

        Begin( channel, () => ar = channel.BeginMethodFoo( null, channel ) );
        return ar;
    }

    public Bar[] EndMethodFoo ( IAsyncResult ar )
    {
        IServiceFoo channel = null;
        channel = _factory.GetChannel();
        return channel.EndMethodFoo( ar );
    }
}

Which can then be used in a method:

 ServiceFooCoordinator _coordinator;

 var asyncResult = _coordinator.BeginMethodFoo();
 try
 {
   var result = _coordinator.EndMethodFoo( asyncResult );
 }
 catch ( Exception )
 { }

Which gets you your asynchronous call in a sychronous manner.

Rus
+1  A: 

I have to ask; why? The point is to provide your user with a fluid experience and waiting on a web service call will not necessarily do that. I suppose you want the full block of content to load before the Silverlight control loads. In that case, I would turn to caching the content rather than forcing the client to wait indefinitely.

Chris Stewart