Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于布尔值的线程阻塞_C#_.net_Multithreading_Task Parallel Library_Blocking - Fatal编程技术网

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。