1

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

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

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

有一个HaltProcessing属性,当设置为 true 时,会暂停队列项的处理。我通过if statement上面看到的来做到这一点。

有没有更好的方法来阻塞线程什么时候阻塞,HaltProcessing什么时候true解除阻塞false

4

4 回答 4

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
于 2013-11-14T07:09:43.160 回答
2

我建议您退后一步看大局:如果设置了,您不需要(也不希望)循环运行HaltProcessing

所以我的方法是将逻辑放入HaltProcessing设置器中:

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

要实现这一点:

  • 如果看到标志,循环线程(运行循环方法)应该退出
  • 如果应该启动循环线程,清除标志,然后锁定线程句柄,并在赢得潜在的锁定竞争时启动线程
于 2013-11-14T07:16:34.200 回答
1
  1. Task.Delay()不会做任何事情,它返回一个Task将在给定间隔后完成的。如果您对此不做任何事情Task,就好像您没有调用它一样。
  2. 如果您想在集合中有一些项目时处理集合中的项目并在集合为空时阻止,您应该使用BlockingCollection.

    在集合为空时等待某个时间是不好的,原因有两个:

    1. 将项目添加到队列后,您不会立即开始处理它。
    2. 当集合为空时,您正在浪费 CPUCount一遍又一遍地检查。
  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();
    }
    

有了这一切,你的循环看起来像这样:

while (true)
{
    WaitUntilProcessingAllowed();

    ProcessQueueMessage(blockingCollection.Take());
}

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

于 2013-11-14T12:14:40.980 回答
0

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

你应该有一些逻辑要说:

  • 如果有项目 -> 处理它们
  • 否则 -> 去睡觉
  • 当新项目进来时->唤醒处理器。
于 2013-11-14T07:09:55.180 回答