views:

594

answers:

3

The backgound: I am trying to forward the server-side ApplyChangeFailed event that is fired by a Sync Services for ADO 1.0 DBServerSyncProvider to the client. All the code examples for Sync Services conflict resolution do not use WCF, and when the client connects to the server database directly, this problem does not exist. My DBServerSyncProvider is wrapped by a head-less WCF service, however, and I cannot show the user a dialog with the offending data for review.

So, the obvious solution seemed to be to convert the HTTP WCF service that Sync Services generated to TCP, make it a duplex connection, and define a callback handler on the client that receives the SyncConflict object and sets the Action property of the event.

When I did that, I got a runtime error (before the callback was attempted):

System.InvalidOperationException: This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.

So I did what the message suggested and decorated both the service and the callback behavior with the Multiple attribute. Then the runtime error went away, but the call results in a "deadlock" and never returns. What do I do to get around this? Is it not possible to have a WCF service that calls back the client before the original service call returns?

Edit: I think this could be the explanation of the issue, but I am still not sure what the correct solution should be.

+1  A: 

After updating the ConcurrencyMode have you tried firing the callback in a seperate thread?

This answer to another question has some example code that starts another thread and passes through the callback, you might be able to modify that design for your purpose?

mundeep
After thinking this through some more, I realized that the thread behind the link in my post has an excellent reasoning for this issue. The problem is not that the callback has to be made in a separate thread. Since it runs on the server, this is not relevant. The deadlock happens on the client. I will post the answer with my code.
cdonner
A: 

By starting the sync agent in a separate thread on the client, the callback works just fine:

    private int kickOffSyncInSeparateThread()
    {
        SyncRunner syncRunner = new SyncRunner();
        Thread syncThread = new Thread(
               new ThreadStart(syncRunner.RunSyncInThread));

        try
        {
            syncThread.Start();
        }
        catch (ThreadStateException ex)
        {
            Console.WriteLine(ex);
            return 1;
        }
        catch (ThreadInterruptedException ex)
        {
            Console.WriteLine(ex);
            return 2;
        }
        return 0;
    }

And this is my SyncRunner:

class SyncRunner
{
    public void RunSyncInThread()
    {
        MysyncAgent = new MySyncAgent();

        syncAgent.addUserIdParameter("56623239-d855-de11-8e97-0016cfe25fa3");
        Microsoft.Synchronization.Data.SyncStatistics syncStats = 
              syncAgent.Synchronize();
    }
}
cdonner
A: 

HI Cdonner,

I am facing the same problem. I want to bring the conflict to client side and handle it in client side. I am using WCF. I am not familiar with WCF. So if you could post the sample to do this. It would be great help.

Thanks in Advance..

UExcel
I don't have a sample, what I have would be too involved to post, even in an email.
cdonner