views:

56

answers:

4

I have the scenario where a command comes in over a socket which requires a fair amount of work. Only one thread can process the data at a time. The commands will come in faster than can process it. Over time there will be quiet a back log.

The good part is that I can discard waiting threads and really only have to process the last one that is waiting - (or process the first one in and discard all the other once). I was thinking about using a semaphore to control the critical section of code and to use a boolean to see if there are any threads blocking. If there are blocking thread I would just discard the thread.

My mind is drawing a blank on how to implement it nicely I would like to implement it with out using an integer or boolean to see if there is a thread waiting already.

I am coding this in c#

+1  A: 

I believe you are looking for the lock statement.

private readonly object _lock = new object();

private void ProccessCommand(Command command)
{
    lock (_lock)
    {
        // ...
    }
}
ChaosPandion
This will work to ensure that only one thread is performing work, however I only ever want one thread blocking on the lock. If there is a thread blocking on the lock I want to discard the thread.
John Soer
A: 

It sounds like you just need to use the lock statement. Code inside a lock statement will allow only one thread to work inside the code block at once.

More info: lock Statement

APShredder
+1  A: 

You can use Monitor.TryEnter to see whether a lock is already taken on an object:

void ProcessConnection(TcpClient client)
{
    bool lockTaken = false;

    Monitor.TryEnter(lockObject, out lockTaken);

    if (!lockTaken)
    {
        client.Close();
        return;
    }

    try
    {
        // long-running process here
    }
    finally
    {
        Monitor.Exit(lockObject);
        client.Close();
    }
}

Note that for this to work you'll still have to invoke the method in a thread, for example:

client = listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(notused => ProcessConnection(client));

FYI, the lock statement is just sugar for:

Monitor.Enter(lockObject);

try
{
    // code within lock { }
}
finally
{
    Monitor.Exit(lockObject);
}
Ben M
A: 

From the sounds of what you've posted here, you might be able to avoid so many waiting threads. You could queue up the next command to execute, and rather than keep the threads waiting, just replace the command to execute next after the current command finishes. Lock when replacing and removing the "waiting" command.

Something like this:

class CommandHandler
{
    Action nextCommand;
    ManualResetEvent manualResetEvent = new ManualResetEvent(false);
    object lockObject = new object();

    public CommandHandler()
    {
        new Thread(ProcessCommands).Start();                       
    }

    public void AddCommand(Action nextCommandToProcess)
    {
        lock (lockObject)
        {
            nextCommand = nextCommandToProcess;
        }
        manualResetEvent.Set();
    }

    private void ProcessCommands()
    {
        while (true)
        {
            Action action = null;
            lock (lockObject)
            {
                action = nextCommand;
                nextCommand = null;
            }
            if (action != null)
            {
                action();
            }
            lock (lockObject)
            {
                if(nextCommand != null)
                    continue;
                manualResetEvent.Reset();
            }

            manualResetEvent.WaitOne();
        }
    }
}

check out: ManualResetEvent

It's a useful threading class.

Eric Dahlvang