7


2

FaultExceptionをキャッチした後、wcfクライアントプロキシのAbort()メソッドがセッションを解放しない

IISとwcfクライアントでホストされる単純なwcfサービスを作成し、wcfサービスからFaultExceptionをキャッチしてからclient.Abort()を呼び出してセッションを解放すると(Microsoftのサンプルによると)解放されないことがわかりましたセッションを開始し、11回目のコールで電話を切ります。

これが例です。

Wcfサービス:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}


public class Service1 : IService1
{
    public string GetData(int value)
    {
        throw new FaultException("Exception is here");

        return string.Format("You entered: {0}", value);
    }
}

クライアント:

class Program
{
    static void Main(string[] args)
    {
        Service1Client client = null;

        for(int i = 0; i < 15; i++)
        {
            try
            {
                client = new Service1Client();
                client.GetData(100);
            }
            catch (TimeoutException timeoutEx)
            {
                Console.WriteLine(timeoutEx);
                client.Abort();
            }
            catch (FaultException faultEx)
            {
                Console.WriteLine(faultEx);
                client.Abort();
            }
            catch (CommunicationException commEx)
            {
                Console.WriteLine(commEx);
                client.Abort();
            }
      }
   }

}

ただし、catch(FaultException)のclient.Abort()をclient.Close()に置き換えると、すべてがチャームのように機能し、wcf-serviceメソッドの11回目の呼び出し後にロックはありません。

なぜそうなるのでしょうか? FaultExceptionがキャッチされた後、Abort()メソッドがセッションをクリーンアップしないのはなぜですか?

2 Answer


6


2つのこと

  • `Abort()`は、通信チャネルが 障害状態。 `Close()`を使用すると、クライアントはサービスと通信しようとし、サービスインスタンスを閉じるように指示します。 通信チャネルがFaulted状態にある場合、クライアントからサービスへの通信ができないことを意味します。 その場合、少なくとも_client_が閉じられるように、 `Abort()`を呼び出す必要があります。 サービスインスタンス/セッションはサーバー上で引き続き有効であり(2つの間に通信がないため)、インスタンスタイムアウトが発生するまでその状態を維持します。 障害が発生したチャンネルで「Close()」を呼び出した場合、より多くのエラーがスローされます。

  • サービスが「FaultException」をスローしています。 これは、という意味ではありません 通信チャネルは障害状態になります。 i.e. 同じクライアントを使用して引き続き電話をかけることができます。 したがって、あなたの例では、 `Abort()`を呼び出すべきではありません。

  • tl; dr * `Abort()`はクライアントのみを閉じます。 サービスインスタンス/セッションはまだ生きています。

以下を使用して、通信チャネルの状態を確認できます。

ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
   client.Abort();
else
   client.Close();


2


WCFの呼び出しに使用しているこの方法を試しましたか?

class Program
{
static void Main(string[] args)
{
    for(int i = 0; i < 15; i++)
    {
        using Service1Client client = new Service1Client()
        {
        try
        {
            client.GetData(100);
        }
        catch (TimeoutException timeoutEx)
        {
            Console.WriteLine(timeoutEx);
            client.Abort();
        }
        catch (FaultException faultEx)
        {
            Console.WriteLine(faultEx);
            client.Abort();
        }
        catch (CommunicationException commEx)
        {
            Console.WriteLine(commEx);
            client.Abort();
        }
        finally
        {
            client.Close();
        }
        }
  }
}