Dave New
Dave New

Reputation: 40062

Thread blocking based on boolean value

I have a service which processes data from a queue:

while (true)
{
    if(!HaltProcessing)
    { 
        var messages = receivedQueue.GetMessages(MessageGetLimit);

        if (messages.Count() > 0)
        {
            ProcessQueueMessages(messages);
        }
        else
        {
            Task.Delay(PollingInterval);
        }
    }
}

There is a HaltProcessing property which, when set to true, pauses the processing of queue items. I do this through the if statement as seen above.

Is there a better way to block the thread when HaltProcessing is true and unblock when false?

Upvotes: 1

Views: 773

Answers (4)

svick
svick

Reputation: 244928

  1. Your Task.Delay() won't do anything, it returns a Task that will complete after the given interval. If you don't do anything with that Task, it's almost as if you didn't call it.
  2. If you want to process items from a collection when there are some and block when the collection is empty, you should use BlockingCollection.

    Waiting for a certain time when the collection is empty is bad for two reasons:

    1. When an item is added to the queue, you won't start processing it immediately.
    2. You're wasting CPU checking the Count over and over when the collection is empty.
  3. If want to wait while HaltProcessing is true, you can use ManualResetEventSlim for this. Though it's more natural to do that negated:

    private ManualResetEventSlim processingAllowedEvent =
        new ManualResetEventSlim(true);
    
    public bool ProcessingAllowed
    {
        get
        {
            return processingAllowedEvent.IsSet;
        }
        set
        {
            if (value)
                processingAllowedEvent.Set();
            else
                processingAllowedEvent.Reset();
        }
    }
    
    public void WaitUntilProcessingAllowed()
    {
        processingAllowedEvent.Wait();
    }
    

With all this, your loop would look something like this:

while (true)
{
    WaitUntilProcessingAllowed();

    ProcessQueueMessage(blockingCollection.Take());
}

This assumes that you're okay with processing one item after ProcessingAllowed is set to false. If that's not true, you would need more complex synchronization (probably using CancellationToken).

Upvotes: 1

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73492

Yes, you can use "WaitHandles".

AutoResetEvent or ManualRestEvent to achieve it.

private ManualRestEvent signal = new ManualRestEvent(false);//or true based on your req
//Setting true is to allow processing and false is to halt the processing

while (true)
{
    signal.WaitOne();
    var messages = receivedQueue.GetMessages(MessageGetLimit);

    if (messages.Count() > 0)
    {
        ProcessQueueMessages(messages);
    }
    else
    {
        Task.Delay(PollingInterval);
    }
}

bool SetHaltProcessing(bool value)
{
    if(value)
       signal.Reset();
    else
       signal.Set();
}

Use case

SetHaltProcessing(true);//To halt the processing
SetHaltProcessing(false);//To start the processing

Upvotes: 3

Eugen Rieck
Eugen Rieck

Reputation: 65304

I recommend you step back to see the bigger picture: You don't need (and want) the loop to run, if HaltProcessing is set.

So my approach would be to put the logic into the HaltProcessing setter:

  • Set to true: Just set a flag
  • Set to false: Start the loop thread

To implement this:

  • The loop thread (running the loop method) should just exit, if it sees the flag
  • If the loop thread should be started, clear the flag, then lock the thread handle, and on winning a potential lock race start the thread

Upvotes: 2

Noctis
Noctis

Reputation: 11763

You do realize that all you do is run constantly in that loop, checking if the HaltProcessing is true, and when it's false, you process something ... That's busy waiting at it's best, and it's not pretty.

You should have some logic to say:

  • if there are items -> process them
  • else -> go to sleep
  • when new items come in -> wake the processor.

Upvotes: 0

Related Questions