C# 基于布尔值的线程阻塞
我有一个处理队列数据的服务:C# 基于布尔值的线程阻塞,c#,.net,multithreading,task-parallel-library,blocking,C#,.net,Multithreading,Task Parallel Library,Blocking,我有一个处理队列数据的服务: while (true) { if(!HaltProcessing) { var messages = receivedQueue.GetMessages(MessageGetLimit); if (messages.Count() > 0) { ProcessQueueMessages(messages); } else
while (true)
{
if(!HaltProcessing)
{
var messages = receivedQueue.GetMessages(MessageGetLimit);
if (messages.Count() > 0)
{
ProcessQueueMessages(messages);
}
else
{
Task.Delay(PollingInterval);
}
}
}
有一个HaltProcessing
属性,当该属性设置为true时,将暂停队列项目的处理。如上所示,我通过if语句来实现这一点
当停止处理为真时,是否有更好的方法阻止线程,当为假时,是否有更好的方法取消阻止线程?是的,您可以使用“WaitHandles”
或者为了实现它
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();
}
用例
SetHaltProcessing(true);//To halt the processing
SetHaltProcessing(false);//To start the processing
是的,您可以使用“WaitHandles”
或者为了实现它
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();
}
用例
SetHaltProcessing(true);//To halt the processing
SetHaltProcessing(false);//To start the processing
您确实意识到,您所做的一切就是在该循环中不断运行,检查停止处理
是否为真,当它为假时,您会处理一些事情。。。这是忙碌的等待在最好的时候,这是不漂亮的
你应该有一些逻辑来说:
- 如果有项目->处理它们
- 否则->去睡觉
- 当新项目进入->唤醒处理器
您确实意识到,您所做的只是在该循环中不断运行,检查停止处理
是否为真,当它为假时,您会处理一些事情。。。这是忙碌的等待在最好的时候,这是不漂亮的
你应该有一些逻辑来说:
- 如果有项目->处理它们
- 否则->去睡觉
- 当新项目进入->唤醒处理器
我建议您后退一步,看看更大的图景:如果设置了HaltProcessing
,您不需要(也不希望)循环运行
因此,我的方法是将逻辑放入HaltProcessing
setter:
- 设置为true:只需设置一个标志
- 设置为false:启动循环线程
要落实这一点:
- 如果循环线程(运行循环方法)看到该标志,它应该退出
- 如果应该启动循环线程,请清除该标志,然后锁定线程句柄,并在赢得潜在的锁定竞赛后启动该线程
我建议您后退一步,看看更大的图景:如果设置了HaltProcessing
,您不需要(也不希望)循环运行
因此,我的方法是将逻辑放入HaltProcessing
setter:
- 设置为true:只需设置一个标志
- 设置为false:启动循环线程
要落实这一点:
- 如果循环线程(运行循环方法)看到该标志,它应该退出
- 如果应该启动循环线程,请清除该标志,然后锁定线程句柄,并在赢得潜在的锁定竞赛后启动该线程
您的Task.Delay()
不会做任何事情,它返回一个任务
,该任务将在给定的时间间隔后完成。如果你没有对这个任务做任何事情
,就好像你没有调用它一样
如果要在集合中有项目时处理其中的项目,并在集合为空时阻止,则应使用BlockingCollection
当集合为空时等待一定时间是不好的,原因有两个:
将项目添加到队列时,您不会立即开始处理它
当集合为空时,您正在浪费CPU反复检查计数
如果要在停止处理
为真
时等待,可以使用ManualResetEventSlim
进行此操作。尽管这样做更自然,但否定:
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();
}
有了这些,您的循环将如下所示:
while (true)
{
WaitUntilProcessingAllowed();
ProcessQueueMessage(blockingCollection.Take());
}
这假设在ProcessingAllowed
设置为false
后,您可以处理一个项目。如果不是这样,则需要更复杂的同步(可能使用CancellationToken
)
您的Task.Delay()
不会做任何事情,它返回一个任务
,该任务将在给定的时间间隔后完成。如果你没有对这个任务做任何事情
,就好像你没有调用它一样
如果要在集合中有项目时处理其中的项目,并在集合为空时阻止,则应使用BlockingCollection
当集合为空时等待一定时间是不好的,原因有两个:
将项目添加到队列时,您不会立即开始处理它
当集合为空时,您正在浪费CPU反复检查计数
如果要在停止处理
为真
时等待,可以使用ManualResetEventSlim
进行此操作。尽管这样做更自然,但否定:
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();
}
有了这些,您的循环将如下所示:
while (true)
{
WaitUntilProcessingAllowed();
ProcessQueueMessage(blockingCollection.Take());
}
这假设在ProcessingAllowed
设置为false
后,您可以处理一个项目。如果不是这样,则需要更复杂的同步(可能使用CancellationToken
)。如果不需要跨进程同步,通常使用ManualRestEventSlim
更有效。另外,这个Task.Delay()
没有任何作用,您从问题中复制了这个bug。如果您不需要跨进程同步,使用ManualRestEventSlim
通常更有效。另外,这个Task.Delay()
没有任何作用,您从问题中复制了这个bug。