我有一个在 silverlight 应用程序中使用的自托管 WCF 服务。我正在尝试将用户 guid 列表存储在 IDictionary 对象中。每次用户点击服务时,它都会更新用户的日期时间,以便我可以跟踪哪些用户有活动的“会话”。问题是,每次我点击服务时,列表都是空的。它似乎正在删除每个肥皂请求的值?
您能否将信息存储在可跨多个服务请求使用的自托管服务中?
提前致谢!
如果您需要在请求之间存储内容,您将需要创建一个具有适当锁定的静态字典来存储这些请求,或者将此信息存储在数据库(或其他外部存储)中并检查它是否存在于每个方法调用中。这样做的原因是服务类在每个客户端请求上都被实例化。
由于您已经在用户点击服务时更新了用户的日期时间,因此最好通过与日期时间字段进行比较来查看这是否是活动用户。这样做的好处是每次调用都准确(如果重新启动服务,字典可能与数据库不同步)。数据库已经有了处理并发的机制,因此您可以将复杂性推向数据存储,而不是围绕单个对象滚动您自己的锁定解决方案。
如果第二个解决方案不够快(并且您已经对应用程序进行了分析并确定它是瓶颈),那么另一个选择是在数据库前面使用某种缓存解决方案,以便在开始之前先在内存中检查数据到分贝。这个缓存对象需要像字典一样是静态的,并且与任何其他多线程应用程序一样具有相同的锁定缺陷。
编辑:如果这个托管的 WCF 服务被用作 silverlight 应用程序用户的会话存储,并且数据没有存储在外部数据存储中,那么您最好确保跟踪它们是否处于活动状态不是关键任务。无法保证此数据与描述的一样正确。
根据接受的答案,如果您的服务出现故障并需要重新启动(因为这是自托管的,建议您监控故障事件),您必须处置服务主机并实例化一个新主机。保留 Guid 数据的唯一方法是在重新启动之间将其反弹到服务(假设主机应用程序本身没有重新启动,这是一个不同的问题)。
private Dictionary<Guid,string> _session;
Service service = new Service(_session);
_serviceHost = new ServiceHost(service, GetUriMethodInHostApp());
最好将其存储在外部并按照@marc_s 的建议进行查找。然后这种复杂性就消失了。
它基于每个实例。即默认无会话。
看看这个
当服务合同将 System.ServiceModel.ServiceContractAttribute.SessionMode 属性设置为 System.ServiceModel.SessionMode.Required 时,该合同表示所有调用(即支持调用的底层消息交换)必须是同一对话的一部分.
您需要更改InstanceContextMode
. 您可以通过将以下编译器指令添加到 WCF 类来做到这一点:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
这会将 WCF 服务作为各种单例运行。查看有关WCF 实例上下文模式的更多信息
然后你应该用你的单例对象构建你的服务主机。这是一个工作示例的代码,我正在做类似的事情:
private ServiceHost serviceHost;
if (serviceHost != null)
serviceHost.Close();
if (log.IsInfoEnabled)
log.Info("Starting WCF service host for endpoint: " + ConfiguredWCFEndpoint);
// Create our service instance, and add create a new service host from it
ServiceLayer.TagWCFService service = new ServiceLayer.TagWCFService(ApplicationName,
ApplicationDescription,
SiteId,
ConfiguredUpdateRateMilliseconds);
serviceHost = new ServiceHost(service, new Uri(ConfiguredWCFEndpoint));
// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();
正如其他人礼貌地指出的那样,如果您不熟悉它的工作原理或者它不适合您的特定应用程序,这可能会产生“后果”。