簡體   English   中英

何時在WCF服務中調用析構函數

[英]When is destructor called in a WCF service

我需要創建一個維護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

程序員無法控制何時調用析構函數,因為這是由垃圾收集器決定的。 垃圾收集器檢查應用程序不再使用的對象。 如果它認為某個對象有資格進行銷毀,它會調用析構函數(如果有的話)並回收用於存儲對象的內存。 程序退出時也會調用析構函數。

您的實施存在問題。 要保留數據,您使用的是析構函數。 這是錯誤的,因為無法確定性地調用析構函數,它們在單獨的終結隊列中處理。 這意味着即使您已經銷毀了該對象,也可能無法立即調用其析構函數。

如何解決這個問題
刪除析構函數並使用IDisposable模式,將save邏輯放入Dispose。 會話終止后,WCF將調用IDisposable.Dispose

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

編輯
請看這個答案的評論。 我實際上同意IDisposable不是數據庫提交的正確位置,以前沒有發生過。 除了注釋中提供的解決方案,您還可以使用顯式會話划分

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM