初学者 WCF 设置/实现设计方法
下图是VS2008中实现Cient和Host之间WCF的解决方案。客户端是一个简单的 Windows 窗体应用程序,主机是一个控制台应用程序。我打算使用 Windows 服务作为主机,但现在我使用控制台应用程序来简化和调试。
两者之间的通信是使用netNamedPipeBinding的DCCService(WCF部分);客户端和主机将驻留在同一台机器上。另外,我知道将 WCF 服务与主机分开是一个很好的做法,这样主机就可以轻松更改,这对我来说很好。
这是我的难题:客户调用的工作应该在哪里完成?
我希望我的服务做的工作是在后台以设定的时间间隔不断轮询硬件控制器。而 DCCService 向任何想要了解此数据的客户端公开方法。
硬件控制器代码(setup()、connect()、work() 等)应该在 DCCService 项目还是主机项目中完成?如果是在主机项目中完成,DCCService 类如何从主机项目中的 Controller 类中获取数据?同样,如果 Controller 类位于 DCCService 项目中,该怎么做?哪个更好?
我想我在这里遗漏了一些相当基本的东西。我很感激您的帮助或建议。如果我需要更清楚,请告诉我。
瑞安·R。
See the figure below for a solution in VS2008 which implements WCF between a Cient and a Host. The Client is a simple Windows Form Application and the Host is a Console Application. I intend to use a Windows Service as the Host, but for now I am using a Console Application for simplicity and debugging.
The communication between the two is the DCCService (WCF portion) using netNamedPipeBinding; the Client and Host will all reside on the same machine. Also, I know it is good practice to separate the WCF service from the Host, so that the Host can easily be changed, which is good in my case.
Here is my conundrum: Where should the work be done that clients will call?
The work I want my service to do is to poll a hardware controller at a set interval constantly in the background. While the DCCService exposes methods to any clients that want to know about this data.
Should the hardware controller code (setup(), connect(), work() etc.) be done in DCCService Project or Host Project? If it is done in the Host Project how does the DCCService class grab the data from the Controller class in the Host project? Likewise, how would this be done if Controller class were in DCCService Project? Which is better?
I think I am missing something fairly basic here. I appreciate the help or advice. Please let me know if I need to be more clear.
Ryan R.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
轮询设备的代码在逻辑上是 WCF 服务的一部分,而不是宿主项目。代码是否物理驻留在 WCF 服务项目中或 WCF 服务项目引用的类库中是个人喜好。
我是这样做的。
我有一个托管在 Windows 服务中的 WCF CollectionService。 CollectionService 项目显然有一个
CollectionService
类,它实现了支持 WCF 的ICollectionService
接口,这是客户端与 CollectionService 交互的方式。在同一个项目中,我有一个
Collector
类,它具有私有构造函数,可防止在类范围之外创建该类的实例。该类有一个它维护的私有静态收集器
列表。该类还有两个静态函数 -Start()
和Stop()
。当客户端想要启动
Collector
时,它会调用CollectionService的Start()
操作。此 CollectionService 依次调用静态Collector.Start()
函数,该函数创建一个Collector
实例并将其存储在Collectors
的静态列表中。当客户端希望停止Collector
时,它会调用CollectionService的Stop()
操作,该操作转换为对静态Collector.Stop()的调用
函数,停止Collector
并将其从列表中删除。当
Collector
实例化时,它会启动一个新线程,开始收集数据并将其提供给感兴趣的各方。 新线程是关键。否则,Collector
实例将只是位于Collectors
列表中,而不执行任何操作。因为我正在处理线程,所以显然我必须处理同步问题,例如同步对
Collectors
静态列表的访问。我不希望客户端尝试启动Collector
,而其他人则尝试关闭它。简而言之就是这样。
如果您还没有创建 Windows 服务,这里有我写的两篇 SO 帖子,提供了如何创建 Windows 服务的分步说明。
Windows服务
.NET Windows 服务启动正确
安装后?
第一个链接基本上可以让您访问该服务;第二个展示了如何在不需要
InstallUtil
的情况下安装/卸载它。我希望这有帮助。
编辑
如果只有一个
Controller
可以运行,那么启动Controller
的后续调用可能会被忽略,可能会返回一条指示它是的消息已经运行了。如果您希望多个客户端访问控制器中的数据,这非常简单。您只需要维护订阅者列表即可。
Controller
只是将数据发送到列表中的任何订阅者。WCF 中已经存在这样的发布-订阅框架。您可以在此处阅读详细信息:
有关单向呼叫您需要了解的内容,回调和事件
您可以从 Juval Lowy 的网站 IDesign.net 免费下载此框架。我使用这个概念向感兴趣的各方发出 CollectionService 事件信号。我希望您可以使用相同的概念向多个客户端提供数据。
The code that polls the device is logically part of your WCF service, not the host project. Whether the code physically resides in the WCF service project or a class library referenced by the WCF service project is personal preference.
Here's how I've done it.
I have a WCF CollectionService that is hosted in a Windows service. The CollectionService project obviously has a
CollectionService
class that implements the WCF-enabledICollectionService
interface, which is how clients interact with the CollectionService.In this same project, I have a
Collector
class that has a private constructor, preventing instances of the class from being created outside the scope of the class. The class has a private static list ofCollectors
that it maintains. The class also has two static functions -Start()
andStop()
.When a client wants to start a
Collector
, it invokes theStart()
operation of the CollectionService. This CollectionService, in turn, calls the staticCollector.Start()
function which creates aCollector
instance and stores it in the static list ofCollectors
. When a client wishes to stop theCollector
, it invokes theStop()
operation of the CollectionService, which translates into a call to the staticCollector.Stop()
function, stopping theCollector
and removing it from the list.When a
Collector
is instantiated, it starts a new thread that begins collecting data and making it available to interested parties. The new thread is the key. Otherwise, theCollector
instance would simply sit in the list ofCollectors
and not do anything.Because I'm dealing with threads, obviously I have to deal with synchronization issues, like synchronizing access to the static list of
Collectors
. I don't want a client trying to start aCollector
while someone else is trying to shut it down.That's it in a nutshell.
If you have not created the Windows service yet, here are two SO posts that I've written giving step-by-step instructions for how to do it.
Windows service
.NET Windows Service start right
after the installation?
The first link basically gets you to the service; the second shows how to install/uninstall it without requiring
InstallUtil
.I hope this helps.
EDIT
If only one
Controller
can be running, then subsequent calls to start aController
could simply be ignored, possibly with a return message indicating it is already running.If you want multiple clients to access the data from the
Controller
, this is pretty straightforward. You simply need to maintain a list of subscribers. TheController
simply sends the data to any subscribers in the list.Such a Publish-Subscribe framework in WCF already exists. You can read the details here:
What You Need To Know About One-Way Calls, Callbacks, And Events
You can download this framework for free from Juval Lowy's website, IDesign.net. I am using this concept to signal CollectionService events to interested parties. I expect you can use the same concept to provide data to multiple clients.
在我看来,您需要一个 Windows 服务来托管 (1) 轮询硬件控制器的代码和 (2) WCF 服务主机。在这种情况下,服务管道代码(即继承 ServiceBase 和 WCF 服务主机的类)最好保留在服务 exe 中,而实际功能则保留在类库中,您可以从服务 exe 中引用该类库。
我这样做的方法是有一个后台组件来轮询硬件控制器并维护“当前状态”,该状态将存储在内存中(可能作为单例)或数据库中。然后编写 WCF 服务来在呼叫传入时查询当前状态。HTH
。
Sounds to me like you need a Windows service to host (1) the code that polls the hardware controller and (2) the WCF service host. In that case, the service plumbing code (i.e. the class inheriting ServiceBase and the WCF service host) is best kept in the service exe, and the actual functionality in a class library, which you can reference from the service exe.
The way I would do it is to have a background component that polls the hardware controller and maintains a "current state", which would be stored either in memory (as a singleton perhaps) or in a database. Then write the WCF service to query that current state as calls come in.
HTH.