WCF嵌套回调

发布于 2024-07-23 09:48:51 字数 1196 浏览 6 评论 0 原文

背景:我正在尝试转发服务器端 ApplyChangeFailed 事件,由 ADO 1.0 DBServerSyncProvider 的同步服务向客户端触发。 Sync Services 冲突解决的所有代码示例均未使用 WCF,当客户端直接连接服务器数据库时,不存在此问题。 但是,我的 DBServerSyncProvider 是由无头 WCF 服务包装的,我无法向用户显示包含有问题数据的对话框以供查看。

因此,显而易见的解决方案似乎是将 Sync Services 生成的 HTTP WCF 服务转换为 TCP,使其成为双工连接,并在接收 SyncConflict 对象并设置事件的 Action 属性。

当我这样做时,我收到了运行时错误(在尝试回调之前):

System.InvalidOperationException:此操作会死锁,因为 在当前消息完成处理之前,无法收到回复。 如果 如果您希望允许无序消息处理,请指定 ConcurrencyMode CallbackBehaviorAttribute 上可重入或多次。

因此,我按照消息的建议进行操作,并使用 Multiple 属性修饰服务和回调行为。 然后运行时错误消失了,但调用导致“死锁”并且永远不会返回。 我该怎么做才能解决这个问题? 是否不可能有一个 WCF 服务在原始服务调用返回之前回调客户端?

编辑:我认为这个 可能是问题的解释,但我仍然不确定正确的解决方案应该是什么。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

勿忘初心 2024-07-30 09:48:51

更新 ConcurrencyMode 后,您是否尝试在单独的线程中触发回调?

这个答案另一个问题有一些启动另一个问题的示例代码线程并通过回调,您也许可以根据您的目的修改该设计?

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?

写给空气的情书 2024-07-30 09:48:51

通过在客户端上的单独线程中启动同步代理,回调可以正常工作:

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

这是我的 SyncRunner:

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

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

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文