如何在 Windows 服务中设置可以访问 Windows 服务中的状态信息的 WCF ServiceHost

发布于 2024-08-01 16:10:02 字数 610 浏览 1 评论 0原文

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

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

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

修订:
我在 Windows 服务中实例化 WCF服务契约。 实例化时分配的任何状态信息可供连接到该服务的所有客户端使用。

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

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

I have a written a Windows Service in C#. It is functioning and performing well. I have added a WCF service to the Windows service to enable client applications to connect to the Windows service and obtain stateful information from the Windows service.

I configured the WCF service to be a singleton, so that the same service instance is used to handle all requests from all clients as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

All clients are able to connect and have access to the same stateful information within the WCF service. However, I am running into the following peculiar behavior.

Revised:
I instantiate the WCF service contract within my Windows Service. Any stateful information assigned at the time of instantiation is available to all clients that connect to the service.

However, any stateful information added to the service contract instance later directly from the Windows Service (not by clients) is not visible to clients that connect to the service. It is as if there are two instances of the service contract: One for the Windows Service and one for the clients that connect to the WCF service.

What is the recommended (best) way to instantiate a WCF service and have it be able to access stateful information available within the Windows Service?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫罗兰の梦幻 2024-08-08 16:10:02

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

I would recommend doing an end-run around this by holding your state in a static member, so that it doesn't matter whether or not WCF is creating a new instance for each call or reusing one. This solves the problem and simplifies the code.

终陌 2024-08-08 16:10:02

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

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

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

为什么WCF服务需要单例? 难道您不能使用“每次调用”并仍然获取 NT 服务中的状态信息吗?

收到请求后,就会创建服务对象的实例(服务类,实现服务接口)。 您现在如何访问 NT 服务中的状态信息? 当您真正需要它时,您是否也不能从新创建的服务实例中执行此操作?

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

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

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

马克

Why does the WCF service have to have stateful information? Couldn't that be stored in a database and accessed when needed?

WCF does allow Singleton instances for services - but it's usually discouraged to use this, unless you absolutely, positively have to. Typically, it's easier and scales much better if you can store the stateful info in e.g. a database table and let clients access that using a normal, per-call WCF service.

UPDATE:
OK, another idea: you'll always only gonna have a single ServiceHost anyway. If you choose the "per-call" instanciation mode (as recommended by all leading experts), the ServiceHost will allocate a thread pool of worker threads which will then service the incoming requests.

Why does the WCF service need to be a singleton? Couldn't you use "per-call" and still get at the stateful information in the NT Service?

A request comes in and an instance of your service object (the service class, implementing the service interface) is created. How do you access the stateful information in the NT service right now? Couldn't you do that from the newly created service instance, too - when you actually need it?

If you have stateful information being held in the NT Service, you'll need to make sure any concurrent access will be properly handled - that's totally independent of whether your WCF service class is a singleton or not.

UPDATE 2:
Using the 'OperationContext.Current.Host', you can access the ServiceHost that hosts a given service instance inside the service method being executed - not sure if you can access the actual NT service instance. But if you create your own custom ServiceHost descendant, which has an additional property "ListOfClients", you should be able to access that list at any time, from any service instance running.

MIND YOU: since there are possibly any number of service requests being processed at any given time, reading the list must be thread-safe, and updating the list from the Windows NT Service is even more "risky" and needs to take these concurrency issues into account! Lock the list if you need to update it - otherwise, you'll have unpredictable results.

Marc

青瓷清茶倾城歌 2024-08-08 16:10:02

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

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

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

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

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

Setting InstanceContextMode.Single will cause the ServiceHost to construct a single instance of your service and use that for all calls. But it sounds like you would like to construct the instance yourself, and populate it with a reference to some shared state. If so, that's called the "well-known instance" pattern and can be accomplished by passing the instance to the ServiceHost constructory, like so:

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

ServiceHost will use the instance you pass in for all calls.

An important consideration when using the Single instance mode (whether the object is "well-known" or constructed by the ServiceHost) is threading. By default WCF will only allow one thread to execute concurrently per service instance. So in the PerCall instance mode, since you'll have multiple service instances, you can support multiple concurrent threads which will improve throughput under normal conditions. But with the Single instance mode you only have one service instance so you'd only run one thread at a time. It depends on the service, but it often makes sense then to switch the concurrency mode to Multiple, which will allow multiple concurrent threads into your service instance, but requires that your service implementation be thread-safe.

Some good docs here: http://msdn.microsoft.com/en-us/library/ms731193.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文