【问题标题】:What is the proper life-cycle of a WCF service client proxy in Silverlight 3?Silverlight 3 中 WCF 服务客户端代理的正确生命周期是什么?
【发布时间】:2009-11-10 20:44:49
【问题描述】:

我在网上找到了对我的问题的混合答案。详细说明问题:

  1. 我应该为每个异步调用实例化一次服务客户端代理,还是应该为每个 Silverlight 应用实例化一次?
  2. 是否应该显式关闭服务客户端代理(就像在我的 ASP.NET MVC 应用程序中同步调用 WCF 服务一样)?

我发现很多博主和论坛发帖人相互矛盾。谁能指出任何明确的来源或证据来一劳永逸地回答这个问题?

【问题讨论】:

  • 答案可能取决于您的服务。创建代理的成本很高,但跟踪单个代理并管理任何错误可能很困难。

标签: wcf silverlight wcf-client wcf-proxy


【解决方案1】:

自 V2 以来,我一直在将 Silverlight 与 WCF 一起使用(现在使用 V4),这就是我发现的。一般来说,打开一个客户端并仅使用该客户端进行所有通信非常有效。如果你不使用 DuplexHttBinding,它也可以做相反的事情,每次打开一个新连接,然后在你完成后关闭它。由于 Microsoft 在 Silverlight 中构建 WCF 客户端的方式,您不会看到始终打开一个客户端与为每个请求创建一个新客户端之间的性能差异。 (但是,如果您要为每个请求创建一个新客户端,请确保您也关闭它。)

现在,如果您正在使用 DuplexHttBinding,即,如果您想从服务器调用客户端上的方法,那么您不要在每次请求时关闭客户端当然很重要。这只是常识。但是,没有任何文档告诉您,但我发现绝对关键的是,如果您使用 DuplexHttBinding,您应该一次只打开一个客户端实例。否则,您将遇到各种令人讨厌的超时问题,这些问题将非常非常难以解决。如果您只有一个连接,您的生活将会变得更加轻松。

我在自己的代码中强制执行此操作的方式是通过单个静态 DataConnectionManager 类运行我的所有连接,如果我在关闭第一个连接之前尝试打开第二个连接,该类会抛出一个 Assert。该课程的一些sn-ps:

    private static int clientsOpen;
    public static int ClientsOpen
    {
        get
        {
            return clientsOpen;
        }
        set
        {
            clientsOpen = value;
            Debug.Assert(clientsOpen <= 1, "Bad things seem to happen when there's more than one open client.");
        }
    }

    public static RoomServiceClient GetRoomServiceClient()
    {
        ClientsCreated++;
        ClientsOpen++;
        Logger.LogDebugMessage("Clients created: {0}; Clients open: {1}", ClientsCreated, ClientsOpen);
        return new RoomServiceClient(GetDuplexHttpBinding(), GetDuplexHttpEndpoint());
    }

    public static void TryClientClose(RoomServiceClient client, bool waitForPendingCalls, Action<Exception> callback)
    {
        if (client != null && client.State != CommunicationState.Closed)
        {
            client.CloseCompleted += (sender, e) =>
            {
                ClientsClosed++;
                ClientsOpen--;
                Logger.LogDebugMessage("Clients closed: {0}; Clients open: {1}", ClientsClosed, ClientsOpen);
                if (e.Error != null)
                {
                    Logger.LogDebugMessage(e.Error.Message);
                    client.Abort();
                }
                closingIntentionally = false;
                if (callback != null)
                {
                    callback(e.Error);
                }
            };
            closingIntentionally = true;
            if (waitForPendingCalls)
            {
                WaitForPendingCalls(() => client.CloseAsync());
            }
            else
            {
                client.CloseAsync();
            }
        }
        else
        {
            if (callback != null)
            {
                callback(null);
            }
        }
    }

当然,烦人的部分是,如果您只有一个连接,您需要捕捉该连接何时意外关闭并尝试重新打开它。然后你需要重新初始化你的不同类注册处理的所有回调。这并不是真的那么困难,但确保它正确完成是很烦人的。当然,该部分的自动化测试即使不是不可能也很困难。 . .

【讨论】:

    【解决方案2】:

    您应该在每次调用时打开您的客户端并在之后立即关闭它。如果您对使用 IE 浏览到 SVC 文件有疑问,请查看那里的示例。

    【讨论】:

    • 在 Silverlight 中使用的异步 WCF 调用的世界中,“立即”是什么意思?在我开始异步调用后关闭它,还是在完成后关闭它?如果是后者,它会引出如果它从未完成会发生什么的问题。
    【解决方案3】:

    WCF 有配置设置,告诉它应该等待调用返回多长时间,我的想法是,当它没有在允许的时间内完成时,AsyncClose 将关闭它。因此调用 client.AsyncClose()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2011-06-29
      • 2018-07-10
      相关资源
      最近更新 更多