[英]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.