简体   繁体   中英

c# Windows Service controlling multiple threads with a single Mutex

I have a Windows service which creates multiple threads; each thread is functionally identical but points at a different server to do it's processing. However each thread also reads some data from an accounts table on the main server.

I also have a console application which inserts, updates and deletes records into the accounts table which all threads look at.

What I need to do is have all the services threads stop processing when the console application runs - the console application needs to wait until all the threads are paused before it starts doing anything. The threads need to continue processing when the console application finishes. This I figured I could do using two mutexs using the following logic:

  1. When the service starts, it obtains the lock on the 'service' mutex to say that it is running, then creates and starts the threads.

  2. When the console application starts, it obtains the 'account' mutex to say that it is running.

  3. The console application then waits on the 'service' mutex until it is released.

  4. On each pass of processing, each thread of the service checks the 'account' mutex, checks to see if the mutex is claimed. If the 'account' mutex is claimed, the thread asks the service to release the 'service' mutex, then waits on the 'account' mutex.

  5. The console application does it's processing.

  6. The console application releases the 'account' mutex, and closes.

  7. With the 'account' mutex released the service threads continue, and ask the service to obtain the 'service' mutex.

My problem here is that I don't know how to get the thread(s) to get the service to obtain or release the 'service' mutex.

I've tried putting the mutex.WaitOne() / mutex.ReleaseMutex() in static methods in the Service.cs, but they (obviously) execute in the threads context (and the release therefore throws an exception due to attempting to release a mutex which the thread doesn't own - I imagine the WaitOne would also cause an error further on as the thread will claim the mutex).

What is the correct approach for this? Can I do something in the thread(s) to get the service to obtain / release the mutex? Should I be using something else instead of a mutex?

I see race conditions being a real problem with any approach here. But a possible, simpler approach would be to use a control table in your database. Within it there are 2 fields: a thread counter which is upped and lowered after each thread starts/finishes and a flag which indicates when the console wants to run - which each thread would check first before running and upping their counter. The console will then check the thread counter reaches zero (either via comet polling or sql dependency).

At least with that approach you can externally observe what your threads are doing and depending on when you set the flags/counters you can mitigate race conditions. (of course if your service or console app crash you'll have dirty data - but cleaning the control table is moot)

If you do want real-time processing however, combining both into one service is the way to go...

Try to avoid controlling/synchronising the worker manager service (windows service) and the console application via mutexes. Rather merge the console application into the windows service.

One way to do this is have the windows service expose a wcf service the console application can use to invoke the code that was previously in the console application itself. (I assume the console application was to allow human intervention)

Now you have all the code/threads requiring synchronisation in the same process.

From here you can use a readwriter lock for the synchronisation, the code previously called from the console application would be the writer, requiing exclusive access during it's operation and the service threads would aquire reader access (and can read concurrently).

If the console app also needs to perform read access and conditionally only perform updates then you can aquire an upgradable lock.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM