何时在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文件

                                    

客户

  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不是数据库提交的正确位置,之前没有发生过。 除了注释中提供的解决方案,您还可以使用显式会话划分