6

Web で自分の質問に対するさまざまな回答を見つけています。質問を詳しく説明するには:

  1. サービス クライアント プロキシは、非同期呼び出しごとに 1 回、または Silverlight アプリごとに 1 回インスタンス化する必要がありますか?
  2. サービス クライアント プロキシを明示的に閉じる必要がありますか (WCF サービスを同期的に呼び出す ASP.NET MVC アプリケーションで行うように)。

多くのブロガーとフォーラムの投稿者が互いに矛盾しているのを見つけました。これに完全に答えるために、決定的な情報源または証拠を誰かが指摘できますか?

4

3 に答える 3

3

私は V2 から WCF で Silverlight を使用しており (現在は V4 で作業しています)、これが私が見つけたものです。一般に、1 つのクライアントを開き、その 1 つのクライアントだけをすべての通信に使用することは非常にうまく機能します。また、DuplexHttBinding を使用していない場合は、反対のことを行って、毎回新しい接続を開き、完了したら閉じることもできます。また、Microsoft が Silverlight で WCF クライアントを設計した方法により、1 つのクライアントを常に開いたままにしておく場合と、要求ごとに新しいクライアントを作成する場合とでは、パフォーマンスに大きな違いは見られません。(ただし、リクエストごとに新しいクライアントを作成している場合は、それも閉じていることを確認してください。)

ここで、DuplexHttBinding を使用している場合、つまりサーバーからクライアントのメソッドを呼び出したい場合は、要求ごとにクライアントを閉じないことがもちろん重要です。それはただの常識です。ただし、どのドキュメントにも記載されていませんが、私が絶対に重要であることがわかったのは、DuplexHttBinding を使用している場合、クライアントのインスタンスを一度に 1 つだけ開く必要があるということです。そうしないと、あらゆる種類の厄介なタイムアウトの問題に遭遇し、トラブルシューティングが非常に困難になります。接続が 1 つあれば、生活は劇的に楽になります。

私自身のコードでこれを強制した方法は、最初の接続を閉じる前に 2 番目の接続を開こうとすると、Assert をスローする単一の静的 DataConnectionManager クラスを介してすべての接続を実行することです。そのクラスからのいくつかのスニペット:

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

もちろん、厄介な部分は、接続が 1 つしかない場合、その接続が意図せずに閉じられたときにトラップして、再度開くようにする必要があることです。次に、さまざまなクラスが処理するために登録されたすべてのコールバックを再初期化する必要があります。それほど難しいことではありませんが、正しく行われていることを確認するのは面倒です。もちろん、その部分の自動テストは、不可能ではないにしても困難です。. .

于 2009-12-19T23:31:46.910 に答える
0

WCFには、呼び出しが返されるまで待機する時間を示す構成設定があります。私の考えでは、許可された時間内に完了しないと、AsyncCloseが閉じます。したがって、client.AsyncClose() を呼び出します。

于 2010-02-15T04:14:25.987 に答える
0

呼び出しごとにクライアントを開き、すぐに閉じる必要があります。疑わしい場合は、IE を使用して SVC ファイルを参照し、そこにある例を見てください。

于 2009-11-11T14:42:50.190 に答える