我需要创建一个维护 WCF 会话的服务。
在构造函数中,我从数据库读取数据,当会话结束时,我必须将其保存回来。
如果我理解正确,当我在客户端上调用 Close() 时,会话结束(我的客户端 ServiceClient 是使用 SvcUtil.exe 创建的)。
当我测试它时,我发现有时会在大约之后调用它。 10 分钟,有时 20 分钟后,有时根本不。
那么什么时候调用析构函数呢?
Service
[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;
}
}
网页配置
<?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>
Client
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();
}
From docs http://msdn.microsoft.com/en-us/library/66x5fx1b%28v=VS.100%29.aspx
程序员无法控制何时调用析构函数
因为这是由垃圾收集器决定的。垃圾
收集器检查不再被使用的对象
应用。如果它认为一个物体有资格被销毁,它
调用析构函数(如果有)并回收用于存储的内存
物体。程序退出时也会调用析构函数。
你的实现有问题。为了保存数据,您正在使用析构函数。这是错误的,因为析构函数不能被确定性地调用,它们是在单独的终结队列中处理的。这意味着即使您已经销毁了该对象,也可能不会立即调用其析构函数。
如何解决这个问题
删除析构函数并使用 IDisposable 模式代替,将保存逻辑放入 Dispose 中。一旦会话终止,WCF将调用IDisposable.Dispose
public class Service:IService, IDisposable
{
public void Dispose()
{
//your save logic here
}
}
EDIT
另请参阅此答案的评论。我其实同意IDisposable
不是数据库提交的正确位置,我之前没有想到。除了评论中提供的解决方案之外,您还可以使用明确的会话划分 http://www.codeproject.com/KB/WCF/Sessions_in_WCF.aspx
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)