6

PerSession では、サービスで Dispose() を起動するにはどうすればよいですか? 以下のコードでは、Dispose() は呼び出されません。.Close() を呼び出したときも、セッションをタイムアウトさせたときも。

サービスを PerCall Dispose() に変更すると、(各メソッド呼び出しで) 呼び出されます。PerSession を使用してセッションを取得しています (serviceStartTime でテスト)。

サービス

[ServiceBehavior (InstanceContextMode=InstanceContextMode.PerSession)]
public class MagicEightBallService : IEightBall, IDisposable
{
    private DateTime serviceStartTime;
    public void Dispose()
    {
        Console.WriteLine("Eightball dispose ... " + OperationContext.Current.SessionId.ToString());
    }
    public MagicEightBallService()
    {
        serviceStartTime = DateTime.Now;
        Console.WriteLine("Eightball awaits your question " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString());
    }
    public string ObtainAnswerToQuestion(string userQuestion)
    {
        return "maybe " + OperationContext.Current.SessionId.ToString() + " " + serviceStartTime.ToLongTimeString();
    }

クライアント

    using (EightBallClient ball = new EightBallClient())
    {    
        while (true)
        {
            Console.Write("Your question: ");
            string question = Console.ReadLine();
            if (string.IsNullOrEmpty(question)) break;
            try
            {
                string answer = ball.ObtainAnswerToQuestion(question);
                Console.WriteLine("8-ball says: {0}", answer);
            }
            catch (Exception Ex)
            {
                Console.WriteLine("ball.ObtainAnswerToQuestion exception " + Ex.Message);
            }               
        }
        ball.Close();
     }

サービス契約

[ServiceContract (SessionMode = SessionMode.Required)]
public interface IEightBall
{
    [OperationContract]
    string ObtainAnswerToQuestion(string userQuestion);

    [OperationContract]
    sDoc GetSdoc(int sID);

    DateTime CurDateTime();
}

ホスト

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_ISampleService" 
                 closeTimeout="00:01:00" openTimeout="00:01:00" 
                 receiveTimeout="00:10:00" sendTimeout="00:10:00">
          <security mode="Message" />
          <reliableSession ordered="true"
                   inactivityTimeout="00:10:00"
                   enabled="true" />
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="MajicEightBallServiceLib.MagicEightBallService"
               behaviorConfiguration="EightBallServiceMEXBehavior" >
        <endpoint address=""
                  binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISampleService"
                  contract="MajicEightBallServiceLib.IEightBall">
        </endpoint>
        <endpoint address="mex"
                  binding ="mexHttpBinding"
                  contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/MagicEightBallService"/>
          </baseAddresses>
        </host>             
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="EightBallServiceMEXBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

namespace MagicEightBallServiceHost
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("**** Console Based WCF Host *****");

            using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
            {
                serviceHost.Open();
                Console.WriteLine("The service is running");
                Console.ReadLine();
            }
        }
    }
}
4

1 に答える 1

10

Dispose()メソッドが起動されます。唯一の質問は「いつ?」です。

その質問に対する答えは、サービスの構成によって異なります。

考えられるシナリオはいくつかあります。

  1. セッションはバインディングでサポートされていません
  2. 通常セッション
  3. 信頼できるセッション

Dispose()PerSessionコンテキスト モードでセッションが閉じられたときに発生します。したがって、さまざまなシナリオでセッションが存続する時間を確認する必要があります。

一部の構成 (たとえば、 default BasicHttpBinding) では、セッションがまったく開始されません。セッションレス構成 PerCallPerSessionコンテキストモードの場合、違いはなく Dispose、メインメソッドが実行された直後にメソッドが呼び出されます。

Enabled の場合Session、クライアントまたはタイムアウトによって明示的に閉じることができます。通常はクライアントによって制御されます。クライアントは、サービスへの最初の呼び出しを行う前にセッションを開始し、Client オブジェクトが閉じられるとセッションを閉じます。

ServiceClient proxy = new ServiceClient();
Console.WriteLine(proxy.GetData(123));
proxy.Close();  

proxy.Close()上記のメソッドは、サーバーでセッションを閉じ、次に実行しDispose()ます。

セッション管理は、クライアントとサーバーの間で追加の呼び出しを実行する必要があるため、パフォーマンスを大きく左右します。

そのため、通常Dispose、クライアントがセッションを閉じたいときに呼び出されます。

クライアントが何らかの理由でセッションを閉じなかった場合、一定期間後にサービス ホストによって閉じられます。その期間はBinding.ReceiveTimeoutプロパティによって制御されます。そのプロパティのデフォルト値は 10 分です。

Dispose()特定のセッション ID を持つサーバーに 10 分間誰もリクエストを送信しなかった場合、セッションは閉じられ、(起動されます)。このデフォルトのタイムアウトはreceiveTimeout、web.config で短い値に設定することで変更できます。

<wsHttpBinding>
  <binding name="wsHttpEndpointBinding" receiveTimeout="00:00:05">
  </binding>
</wsHttpBinding> 

Reliableセッションが有効な場合、ReliableSession.InactivityTimeout が追加でチェックされます。また、デフォルトで 10 分に設定されています。

セルフホステッド サービスと IIS ホステッド サービスで期待どおりに機能します。

次のようにクライアント コードを更新してテストします。

using (EightBallClient ball = new EightBallClient())
{    
    ball.ObtainAnswerToQuestion("test");
    ball.Close();
} 
于 2012-06-15T17:12:15.830 に答える