Search code examples
c#multithreadingsynchronizationsemaphorewcf-callbacks

Multi-threading synchronization using wide scope lock with WCF callbacks


What I want to do is this--

I want to make a proxy call to a service and receive data on a separate thread through an asynchronous callback...the tricky part is that I want to make the foreground thread sleep until all of the data has been retrieved.

The reason I'm not using a synchronous method to do this, is because I'm creating an API for a WCF service that uses Paging and returns data in chunks.
I want my client to be able to use Paging, but I don't want to expose all of my Paging callbacks to my API...I want it to appear as though the API exposes a synchronous data retrieval method.

I've tried using a private static Semaphore (because it is thread agnostic,) that is accessible to the class methods and the callbacks, with a single unit capacity as a means to pause the execution.

First, I use a Semaphore.WaitOne() statement.
Then, I do a Proxy call in the foreground thread, and the service creates a thread that handles the data retrieval, and control is passed back to the client.
In the client, I immediately use a second Semaphore.WaitOne() statement. This should pause the foreground thread execution, which it does. Then, once the "Paging Completed" Callback is executed on a separate thread, I use Semaphore.Release() But the foreground thread never traverses the second Semaphore statement, it stays locked and so the client freezes.

Any ideas what I am doing incorrectly, or is there another locking design that would be more effective?


Solution

  • If what you're trying to accomplish is having the foreground thread wait on data-gathering thread, you may want to consider using Tasks, which would allow you to easily accomplish what you've described here.

    System.Threading.Tasks: http://msdn.microsoft.com/en-us/library/dd235608.aspx

    Some code:

    Task t = new Task(somethingToDo);
    // Fire off the new task
    t.Start();
    
    // Wait for the task to finish...
    t.Wait();
    
    // Do something else...
    

    Make sure to take a look at the details of t.Wait() in the documentation. There are some exceptions you will want to be ready for, in the event that your task fails.