请参阅下图,了解VS2008中在Cient和主机之间实现WCF的解决方案。客户端是一个简单的Windows窗体应用程序,主机是一个控制台应用程序。我打算使用Windows服务作为主机,但是现在我使用控制台应用程序来简化和调试。
两者之间的通信是使用netNamedPipeBinding的DCCService(WCF部分);客户端和主机都将驻留在同一台计算机上。此外,我知道将WCF服务与主机分开是一种好习惯,这样主机就可以轻松更改,这在我的案例中很好。
这是我的难题:客户应该在哪里完成工作?
我希望我的服务所做的工作是在后台不断地以设定的间隔轮询硬件控制器。而DCCService向任何想要了解此数据的客户端公开方法。
硬件控制器代码(setup(),connect(),work()等)是否应在DCCService Project或Host Project中完成?如果在Host Project中完成,DCCService类如何从Host项目的Controller类中获取数据?同样,如果Controller类在DCCService项目中,如何做到这一点?哪个更好?
我想我错过了一些相当基本的东西。我感谢您的帮助或建议。如果我需要更清楚,请告诉我。
Ryan R。
答案 0 :(得分:2)
轮询设备的代码在逻辑上是WCF服务的一部分,而不是主机项目。代码是物理驻留在WCF服务项目中还是由WCF服务项目引用的类库是个人偏好。
以下是我的表现。
我有一个托管在Windows服务中的WCF CollectionService。 CollectionService项目显然有一个CollectionService
类,它实现了启用WCF的ICollectionService
接口,这是客户端与CollectionService交互的方式。
在同一个项目中,我有一个Collector
类,它有一个私有构造函数,可以防止在类的范围之外创建类的实例。该类具有它维护的Collectors
的私有静态列表。该类还有两个静态函数 - Start()
和Stop()
。
当客户端想要启动Collector
时,它会调用CollectionService的Start()
操作。反过来,此CollectionService调用静态Collector.Start()
函数,该函数创建Collector
实例并将其存储在Collectors
的静态列表中。当客户希望停止Collector
时,它会调用CollectionService的Stop()
操作,该操作转换为对静态Collector.Stop()
函数的调用,停止Collector
并删除它来自清单。
当实例化Collector
时,它会启动一个新线程,开始收集数据并使其可供相关方使用。 新线程是密钥。否则,Collector
实例只会位于Collectors
列表中而不会执行任何操作。
因为我正在处理线程,显然我必须处理同步问题,比如同步访问Collectors
的静态列表。我不希望客户尝试启动Collector
而其他人试图关闭它。
简而言之就是这样。
如果您还没有创建Windows服务,这里有两篇我写过的SO帖子,提供了如何执行的逐步说明。
第一个链接基本上可以帮助您获得服务;第二部分展示了如何安装/卸载它而不需要InstallUtil
。
我希望这会有所帮助。
修改强>
如果只有一个Controller
可以运行,那么后续的启动Controller
的调用可能会被忽略,可能会返回一条消息,表明它已在运行。
如果您希望多个客户端访问Controller
中的数据,这非常简单。您只需要维护一个订户列表。 Controller
只是将数据发送给列表中的任何订阅者。
WCF中的这种发布 - 订阅框架已经存在。你可以在这里阅读详细信息:
What You Need To Know About One-Way Calls, Callbacks, And Events
您可以从Juval Lowy的网站IDesign.net免费下载此框架。我正在使用此概念向感兴趣的各方发送CollectionService事件。我希望您可以使用相同的概念为多个客户提供数据。
答案 1 :(得分:0)
听起来像你需要一个Windows服务来托管(1)轮询硬件控制器和(2)WCF服务主机的代码。在这种情况下,服务管道代码(即继承ServiceBase和WCF服务主机的类)最好保存在服务exe中,以及类库中的实际功能,您可以从服务exe引用它。
我这样做的方法是让一个后台组件轮询硬件控制器并维护一个“当前状态”,它将存储在内存中(可能是单例)或数据库中。然后编写WCF服务以在调用进入时查询当前状态。
HTH。