基于布尔值的线程阻塞

时间:2013-11-14 07:06:09

标签: c# .net multithreading task-parallel-library blocking

我有一个处理队列数据的服务:

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

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

有一个HaltProcessing属性,当设置为true时,暂停队列项的处理。我是通过if statement完成的,如上所示。

HaltProcessingtrue时阻止线程是否有更好的方法,在false时阻止线程?

4 个答案:

答案 0 :(得分:3)

是的,您可以使用“WaitHandles”。

AutoResetEventManualRestEvent来实现它。

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

答案 1 :(得分:2)

我建议你退一步看看更大的图片:如果设置了HaltProcessing,你不需要(并希望)循环运行。

所以我的方法是将逻辑放入HaltProcessing setter:

  • 设置为true:只需设置一个标志
  • 设置为false:启动循环线程

实现这个:

  • 循环线程(运行循环方法)应该退出,如果它看到标志
  • 如果应该启动循环线程,清除标志,然后锁定线程句柄,并在赢得潜在的锁定竞赛时启动线程

答案 2 :(得分:1)

  1. 您的Task.Delay()将不会执行任何操作,将返回一个Task,它将在给定的间隔后完成。如果您对Task没有做任何事情,那就好像你没有打电话一样。
  2. 如果要在集合中处理集合中的项目并在集合为空时阻止,则应使用BlockingCollection

    在收集空的时候等待一段时间是不好的,原因有两个:

    1. 当一个项目被添加到队列中时,您将不会立即开始处理它。
    2. 当集合为空时,你正在浪费CPU一遍又一遍地检查Count
  3. 如果您希望等到HaltProcessingtrue,则可以使用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();
    }
    
  4. 有了这一切,你的循环看起来像这样:

    while (true)
    {
        WaitUntilProcessingAllowed();
    
        ProcessQueueMessage(blockingCollection.Take());
    }
    

    这假设您可以在ProcessingAllowed设置为false后处理一个项目。如果不是这样,则需要更复杂的同步(可能使用CancellationToken)。

答案 3 :(得分:0)

你确实意识到你所做的只是在那个循环中不断运行,检查HaltProcessing是否为真,当它是假的时候,你处理的东西......那是忙着等待它最好的,而且它不漂亮

你应该有一些逻辑说:

  • 如果有项目 - >处理它们
  • 其他 - >去睡觉
  • 当新物品进入时 - >唤醒处理器。