4

我用 C# 编写了一个 Windows 服务。它运行良好并且表现良好。我在 Windows 服务中添加了 WCF 服务,以使客户端应用程序能够连接到 Windows 服务并从 Windows 服务中获取有状态信息。

我将 WCF 服务配置为单例,以便使用同一个服务实例来处理来自所有客户端的所有请求,如下所示:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

所有客户端都能够连接并访问 WCF 服务中的相同状态信息。但是,我遇到了以下特殊行为。

修订:我在我的 Windows 服务中
实例化 WCF服务合同。在实例化时分配的任何有状态信息都可用于连接到服务的所有客户端。

但是,稍后直接从​​ Windows 服务(不是由客户端)添加到服务合同实例的任何状态信息对于连接到该服务的客户端是不可见的。就好像服务契约有两个实例:一个用于 Windows 服务,一个用于连接到 WCF 服务的客户端。

实例化 WCF 服务并使其能够访问 Windows 服务中可用的状态信息的推荐(最佳)方法是什么?

4

3 回答 3

2

我建议通过将状态保存在静态成员中来解决此问题,以便 WCF 是为每个调用创建一个新实例还是重用一个实例都无关紧要。这解决了问题并简化了代码。

于 2009-08-14T13:57:58.733 回答
2

为什么 WCF 服务必须有状态信息?不能将其存储在数据库中并在需要时访问吗?

WCF 确实允许服务的 Singleton 实例 - 但通常不鼓励使用它,除非您绝对必须这样做。通常,如果您可以将有状态信息存储在例如数据库表中并让客户端使用普通的每次调用 WCF 服务来访问它,那么它会更容易并且可以更好地扩展。

更新:
好的,另一个想法:无论如何,您将永远只有一个 ServiceHost。如果您选择“每次调用”实例化模式(如所有领先专家的建议),ServiceHost 将分配一个工作线程线程池,然后为传入的请求提供服务。

为什么 WCF 服务需要是单例的?您不能使用“per-call”并仍然获取 NT 服务中的状态信息吗?

一个请求进来,你的服务对象(服务类,实现服务接口)的实例被创建。您现在如何访问 NT 服务中的状态信息?难道你不能从新创建的服务实例中也这样做——当你真正需要它的时候?

如果您在 NT 服务中保存有状态信息,则需要确保正确处理任何并发访问 - 这完全与您的 WCF 服务类是否为单例无关。

更新 2:
使用“OperationContext.Current.Host”,您可以访问在正在执行的服务方法内托管给定服务实例的 ServiceHost - 不确定您是否可以访问实际的 NT 服务实例。但是,如果您创建自己的自定义 ServiceHost 后代,它具有附加属性“ListOfClients”,您应该能够随时从任何正在运行的服务实例访问该列表。

请注意:由于在任何给定时间都可能处理任意数量的服务请求,因此读取列表必须是线程安全的,并且从 Windows NT 服务更新列表更加“冒险”并且需要处理这些并发问题考虑到!如果您需要更新列表,请锁定它 - 否则,您将获得不可预知的结果。

马克

于 2009-08-14T13:59:52.180 回答
1

设置 InstanceContextMode.Single 将导致 ServiceHost 构造您的服务的单个实例并将其用于所有调用。但听起来您想自己构建实例,并使用对某些共享状态的引用来填充它。如果是这样,这称为“众所周知的实例”模式,可以通过将实例传递给 ServiceHost 构造函数来完成,如下所示:

var svc = new MyServiceClass(state);
var host = new ServiceHost(svc, new Uri(..), ...);
...

ServiceHost 将使用您传入的实例进行所有调用。

使用单实例模式(无论对象是“众所周知的”还是由 ServiceHost 构造的)时,一个重要的考虑因素是线程。默认情况下,WCF 将只允许每个服务实例同时执行一个线程。因此,在 PerCall 实例模式下,由于您将拥有多个服务实例,因此您可以支持多个并发线程,这将提高正常情况下的吞吐量。但是在单实例模式下,您只有一个服务实例,因此您一次只能运行一个线程。这取决于服务,但通常将并发模式切换为 Multiple 是有意义的,这将允许多个并发线程进入您的服务实例,但要求您的服务实现是线程安全的。

这里有一些好的文档:http: //msdn.microsoft.com/en-us/library/ms731193.aspx

于 2009-10-17T16:11:11.457 回答