C# · 12月 22, 2021

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