How do you wait/join on a WCF Web Service called from Silverlight?

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

Answers


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();
}

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.


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.


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

serviceClient.GetDataCompleted += (s,e) =>
{
  // Your code here
};
serviceClient.GetDataAsync();

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.


Need Your Help

Symfony: un-secure a backend module for certain kinds of users. How?

php security symfony1 propel

Straight to the point -- I have a Symfony 1.3 / Propel 1.4 project. I have a module which is secured via is_secure: true in its own security.yml. I want this module to be accessible not only for su...

represent IP address as OID

ip oid

how would I represent an IP address as an OID? is there any subtree for generic IP addresses? I'd have expected something like { iso(1) org(3) dod(6) internet(1) protocols ip v4(4) address 127 0 0 ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.