Beginner WCF Setup / Implementation Design Approach
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 const开发者_如何学Goantly 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.
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-enabled ICollectionService
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 of Collectors
that it maintains. The class also has two static functions - Start()
and Stop()
.
When a client wants to start a Collector
, it invokes the Start()
operation of the CollectionService. This CollectionService, in turn, calls the static Collector.Start()
function which creates a Collector
instance and stores it in the static list of Collectors
. When a client wishes to stop the Collector
, it invokes the Stop()
operation of the CollectionService, which translates into a call to the static Collector.Stop()
function, stopping the Collector
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, the Collector
instance would simply sit in the list of Collectors
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 a Collector
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.
- Easiest language for creating a Windows service
- How to make a .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 a Controller
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. The Controller
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.
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.
精彩评论