0

Sorry for the title, I couldn't find better to explain my issue...

I'm having a hard time trying to synchronize different threads in my application. It's probably an easy problem for someone that has a new look on the issue, but after hours of investigations about a deadlock, my head is exploding and I can't find a good and safe way to write my synchronization mechanism :(

Basically, I have a .Net process that runs in multiple threads (everything in a single process, so no need for IPC). I have 4 threads:

  • 1 thread, say it is called SpecificThread. There is a System.Timers.Timer that periodically executes some code.
  • 3 other threads, each running a service that executes some code periodically (while (true) loop + Thread.Sleep(few ms)).

All 3 services must run concurrently. I guarantee their concurrent execution is thread safe. The fourth thread, SpecificThread, must execute its code periodically, but it must block the execution of the 3 other services.

So basically I have SpecificThread that executes code periodically. When SpecificThread wants to execute its code periodically, it must wait for other services to complete their task. When all other 3 services completed their task, it must execute its SpecificCode while other 3 services are blocked. When its SpecificCode is executed, other 3 services can run their code again.

I have a shared instance of a SynchronizationContext object that is shared between all 4 threads. I can use it to synchronize my threads:

public class SynchronizationContext
{
    public void StartService1()
    {
        ...
    }   
    public void StopService1()
    {
        ...
    }
    ...

    public void StartSpecificCode()
    {
        // Some sync here that wait until all 3 services completed their
        // respective tasks
    }
    public void NotifySpecificCodeCompleted()
    {
        // Some sync here that allows services 1 to 3 to execute again
    }
}

The 3 services execution mechanism looks like:

// Only exits the loop when stopping the whole .Net process
while (myService.IsRunning)
{
    try
    {
        this.synchronizationContext.StartService1();

        // Do some job
    }
    finally
    {
        this.synchronizationContext.EndService1();

        // Avoids too much CPU usage for nothing in the loop
        Thread.Sleep(50);
    }
}

The SpecificThread execution mechanism:

// System.Timers.Timer that is instantiated on process start
if (this.timer != null)
{
    this.timer.Stop();
}

try
{
    // Must blocks until computation is possible
    this.synchronizationContext.StartSpecificCode();

    // Some job here that must execute while other 3
    // services are waiting
}
finally
{
    // Notify computation is done
    this.synchronizationContext.NotifySpecificCodeCompleted();

    // Starts timer again
    if (this.timer != null)
    {
        this.timer.Start();
    }
}

I can't figure out how to use critical sections as only SpecificThread must run while other are waiting. I didn't found a way with Semaphore nor AutoResetEvent (their usage introduced a hard-to-debug deadlock in my code). I'm running out of ideas here... Maybe Interlocked static methods would help?

Last word: my code must run with .Net 3.5, I can't use any TPL nor CountdownEvent classes...

Any help is appreciated!

ken2k
  • 48,145
  • 10
  • 116
  • 176

1 Answers1

1

ReaderWriterLockSlim sounds like exactly the tool that will help you the most. Have each of the services take out a read lock inside the body of their loop:

while (true)
{
    try
    {
        lockObject.EnterReadLock();

        //Do stuff
    }
    finally
    {
        lockObject.ExitReadLock();
    }
}

Then your fourth thread can enter a write lock when it wants to do it's work. The way reader/writer locks work is that any number of readers can hold a lock, as long as no writers hold the lock, and there can only be one writer holding the lock at a time. This means that none of the three workers will block other workers, but the workers will bock if the fourth thread is running, which is exactly what you want.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Wow, this sounds to be exactly what I'm looking for! I'm testing it right now – ken2k Mar 28 '13 at 13:27
  • Well, this does the job **perfectly**. My `SynchronizationContext` class now only relies on the `ReaderWriterLockSlim` class, which is incredibly simple and maintainable. Thank you very much, I was just trying to build my own `ReaderWriterLockSlim` class, you saved me hours. Too bad I can't upvote your answer more than once! – ken2k Mar 28 '13 at 13:56