开发者

Threading only block the first thread

开发者 https://www.devze.com 2023-01-06 20:23 出处:网络
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 proces开发者_

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 proces开发者_Python百科s 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#


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);
}


I believe you are looking for the lock statement.

private readonly object _lock = new object();

private void ProccessCommand(Command command)
{
    lock (_lock)
    {
        // ...
    }
}


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消