Reputation: 40062
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
Reputation: 244928
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.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:
Count
over and over when the collection is empty.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
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
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:
To implement this:
Upvotes: 2
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:
Upvotes: 0