John Miner
John Miner

Reputation: 893

How to make WCF Service with a background worker thread?

I have a WCF service that all clients connect to in order to get notifications \ reminders (using a CALLBACK interface they implement). Currently the WCF service is self-hosted, but the plan is to have it hosted in a Windows Service.

The WCF service has a 'Publish', 'Subscribe' and 'Unsubscribe' operations.

I need to have a background worker thread of some sort poll an SQL server database table constantly [every XXX minutes], and look for certain 'reminder' rows. Once it finds them - it should notify all the connected clients.

I thought of 2 ways of achieving this.

.

METHOD A :

Have a separate EXE project (don't want it to be a console, so what should it be - a Windows Service ?) that will start and run a background thread. The background thread will connect to the 'Reminder' service as one of its clients. The background thread will poll the database, and once it finds something - it will send a 'Publish' message to the WCF service, that will make the WCF service send the reminder to all the subscribed clients.

.

METHOD B :

Somehow make the background thread run within the WCF service project, and when it detects a new reminder row in the database, somehow make it 'signal' the WCF service with the info, and the WCF service will then send this info to all subscribed clients.

.

Which method is better ? Any other suggestions ?

Upvotes: 2

Views: 9519

Answers (2)

Tri Q Tran
Tri Q Tran

Reputation: 5690

Method A:

If you were to create two separate hosts (i.e. one for the WCF service and one for the "Polling" service) then you really have only one option to make it all work nicely.

Windows Service communication is very limited (without the help of a service endpoint, e.g. WCF). Therefor, if you were to host your "Polling" service in a Windows Service, you must couple it with a WCF service anyway.

It is then feasible to host both services together in one Windows Service and by manually instantiating the WCF host and passing into the constructor a "Polling" service.

protected override void OnStart(string[] args)
{
    //...

    // This would be you "polling" service that would start a background thread to poll the db.
    var notificationHost = new PollingService();
    // This is your WCF service which you will be "self hosted".
    var serviceHost = new WcfService(notificationHost);

    new ServiceHost(serviceHost).Open();
    //...
}

This is far from ideal because you need to communicate via events between the two services, plus your WCF service must run on singleton mode for manual instantiation to work... So this leaves you with...

Method B:

If you were to host the "Polling" services inside your WCF service, you are going to run into a number of issues.

  1. You need to be aware of the number of instances of the "Polling" services that gets created. If your WCF service has been configured to be instantiated for every session, you could end up with too many "Polling" services and that may end up killing your db/servers.
  2. To avoid the first issue, you may need to set a singleton WCF service, which may lead to a scaling issue in the near future where one WCF service instance is not enough to handle the number of connection requests.

Method C:

Given the drawbacks in Method A and B, the best solution would be to host two independent WCF services.

  1. This is your regular service where you have subscriber/unsubscribe/publish.
  2. This is your polling singleton service with subscribe/unsubscribe.

The idea is that your regular service, upon receiving a subscriber will open a new connection to your polling service or use an existing one (depending on how you configure your session) and wait for a reply. Your polling service is a long running WCF service that polls your db and publish the notification to its subscribers (i.e. the other WCF host).

Pros:

  1. You are assured that there will be only one polling service.
  2. You could scale your solution to host the regular service in IIS and the polling service in Windows Service.
  3. Communication limitations is minimal between the two services and no need for events.
  4. Test each service interdependently through their interfaces.
  5. Low coupling and high cohesion between the services (this is what we want!).

Cons:

  1. More services means more interfaces and contracts to maintain.
  2. Higher complexity.

Upvotes: 1

Erix
Erix

Reputation: 7105

If this is a long running process, a windows service is the perfect solution. Your main Win Service thread will be polling the DB, queuing the results into some kind of supplier/consumer thread safe collection.

You can host a WCF service within the win service, which can then consume (remove) any results from the queue and pass them back to the client as requested (calls into the WCF will come in on their own thread)

This is a pretty common architecture, and not difficult to implement.

Upvotes: 6

Related Questions