微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 什么时候在WCF服务中调用析构函数

我需要创建一个维护WCF会话的服务.
在构造函数中,我从数据库中读取数据,当会话结束时,我必须将其保存回来.

如果我理解正确,当我在客户端调用Close()时,会话结束(我的客户端ServiceClient是用SvcUtil.exe创建的).

当我测试它,我看到它有时被称为约. 10分钟,有时20分钟后,有时甚至没有.

那么析构函数什么时候叫?

服务

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
   public class Service:IService
   {
     private User m_User = null;

     public  Service()
     {
       m_User = User.LoadFromDB();
     }

     ~Service()
     {
       m_User.SavetoDB();
     }

     public void SetName(string p_Name)
     {
       m_User.Name = p_Name;
     }
    }

Web.config文件

<?xml version="1.0"?>
<configuration>
  <system.web>
    <sessionState timeout="2" />
  </system.web>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      <services>
        <service name="Karatasi.Services.B2C"  behaviorConfiguration="ServiceBehavior">
          <host>
            <baseAddresses>
              <add baseAddress="http://localhost:19401/B2C.svc"/>
            </baseAddresses>
          </host>
        <endpoint
           address=""
           binding="wsHttpBinding"
           bindingConfiguration="test"
           contract="Karatasi.Services.IB2C"
         />
        <endpoint
           address="mex"
           binding="mexHttpBinding"
           contract="IMetadataExchange"
         />
       </service>
     </services>
   <bindings>
     <wsHttpBinding>
       <binding name="test" receiveTimeout="00:01:00" >
         <reliableSession enabled="true" ordered="false" inactivityTimeout="00:01:00"/>
       </binding>
     </wsHttpBinding>
    </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="ServiceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="false" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>
</configuration>

客户

ServiceClient serviceClient = null;
    try
    {
      serviceClient = new ServiceClient();
      serviceClient.SetName("NewName");
      Console.WriteLine("Name set");
    }
    catch (Exception p_Exc)
    {
      Console.WriteLine(p_Exc.Message);
    }
    finally
    {
      if (serviceClient != null)
      {
        if (serviceClient.State == CommunicationState.Faulted)
        {
          serviceClient.Abort();
        }
        else
        {
          serviceClient.Close();
        }
      }
      Console.ReadKey();
    }

解决方法

docs

The programmer has no control over when the destructor is called
because this is determined by the garbage collector. The garbage
collector checks for objects that are no longer being used by the
application. If it considers an object eligible for destruction,it
calls the destructor (if any) and reclaims the memory used to store
the object. Destructors are also called when the program exits.

您的实现有问题.要使用析构函数持久化数据.这是错误的,因为析构函数不能被确定性地调用,它们在单独的最终化队列中被处理.这意味着即使您已经销毁对象,也可能不会立即调用它的析构函数.

如何解决这个问题
删除析构函数,并使用Idisposable模式,将保存逻辑放入dispose.会话终止后,WCF将调用Idisposable.dispose

public class Service:IService,Idisposable
{
    public void dispose()
    {
        //your save logic here
    }
}

编辑
Pls也看到这个答案的评论.我实际上同意,Idisposable不是数据库提交的适当位置,以前没有发生.除了评论中提供的解决方案,您可以使用explicit session demarcation

原文地址:https://www.jb51.cc/csharp/91314.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐