WCF Dispose () is not called with InstanceContectMode = PerSession

In PerSession, how can I remove Dispose () in a service to run? In the code below, Dispose () is not called. Not when I call .Close (), nor when I allow a timeout session.

If I change the service to PerCall Dispose (), it is called (with every method call). With PerSession, I get a session (tested with serviceStartTime).

Service

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

Client

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

Service Contract

 [ServiceContract (SessionMode = SessionMode.Required)] public interface IEightBall { [OperationContract] string ObtainAnswerToQuestion(string userQuestion); [OperationContract] sDoc GetSdoc(int sID); DateTime CurDateTime(); } 

Host

 <?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(); } } } } 
+6
source share
1 answer

Dispose() will be launched. The only question is: "When?"

The answer to this question depends on the configuration of the service.

There are several possible scenarios:

  • Session is not supported by binding
  • Regular session
  • Reliable session.

Dispose() started when the session is closed for the context mode of PerSession . Therefore, we need to check how many sessions work in different scenarios.

For some configurations (for example, default BasicHttpBinding ), the session does not start at all. In the case of a configuration without PerCall and PerSession context modes do not differ, and the Dispose method will be called very soon after the main method is executed.

When the Session parameter is enabled, it can be explicitly closed by the client or timeout. It is usually controlled by the client. The client initiates the session before the first service call and closes it when the client object is closed.

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

proxy.Close() method above closes the session on the server, which in turn performs Dispose() .

Session management is a big driver of performance because it requires additional calls between the client and server to complete it.

Thus, usually Dispose is called when the client wants to close the session.

If the client did not close the session for any reason, it will be closed by the service host after a certain period of time. This period is controlled by Binding.ReceiveTimeout . The default value for this property is 10 minutes.

The session will be closed and ( Dispose() started) if no one has sent a request to the server with a specific session identifier within 10 minutes. This default timeout can be changed by setting receiveTimeout to a slightly shorter value in web.config.

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

ReliableSession.InactivityTimeout is additionally checked when a trusted session is enabled. It also defaults to 10 minutes.

It works as expected in IIS self-service and self-service.

Try updating the client code as follows:

 using (EightBallClient ball = new EightBallClient()) { ball.ObtainAnswerToQuestion("test"); ball.Close(); } 
+10
source

Source: https://habr.com/ru/post/918121/


All Articles