7

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()メソッドがセッションをクリーンアップしないのはなぜですか?

4

2 に答える 2

6

2つのこと:

  • Abort()通信チャネルが障害状態のときに使用する必要があります。を使用Close()すると、クライアントはサービスとの通信を試み、必要に応じて、サービスインスタンスを適切に閉じるように指示します。通信チャネルが障害状態の場合は、クライアントからサービスへの通信ができないことを意味します。Abort()そのような状況では、少なくともクライアントが閉じられるように呼び出す必要があります。サービスインスタンス/セッションはサーバー上で引き続き存続し(2つの間に通信がないため)、インスタンスのタイムアウトが発生するまで存続します。Close()障害のあるチャネルを呼び出した場合は、さらに多くのエラーがスローされます。
  • あなたのサービスはを投げていFaultExceptionます。これは、通信チャネルが障害状態になることを意味するものではありません。つまり、同じクライアントを使用して電話をかけることができます。そのため、あなたの例では、を呼び出すべきではありませんAbort()

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

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

ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
   client.Abort();
else
   client.Close();
于 2012-03-01T19:24:29.847 に答える
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();
        }
        }
  }  
}              
于 2011-09-27T17:54:35.457 に答える