2014-02-26 67 views
1

我有一个消费者为生产者消费者图案的一部分:生产者/消费者 - 生产者使用高CPU

简化:

public class MessageFileLogger : ILogger 
{ 
    private BlockingCollection<ILogItem> _messageQueue; 
    private Thread _worker; 
    private bool _enabled = false; 
    public MessageFileLogger() 
    { 
     _worker = new Thread(LogMessage); 
     _worker.IsBackground = true; 
     _worker.Start(); 
    } 

    private void LogMessage() 
    { 
     while (_enabled) 
     { 
      if (_messageQueue.Count > 0) 
      { 

       itm = _messageQueue.Take(); 
       processItem(itm); 
      } 
      else 
      { 
       Thread.Sleep(1000); 
      } 
     } 
    } 
} 

如果删除了

Thread.Sleep(1000); 

的CPU用法爬到一个非常高的(13%),而不是0%,设置线程睡觉。另外,如果我实例化类的多个实例,则CPU使用率以13%的增量上升,并且每个实例都会增加13%。

每隔一分钟左右(可能每隔30秒)将一个新的LogItem添加到BlockingCollection中,并将适用的消息写入文件。

是否有可能线程以某种方式阻止其他线程运行,并且系统需要补偿?

更新: 更新代码,以更好地反映实际的代码

+1

即使队列中没有任何内容,您的发布代码也会处理项目。 –

回答

1

你给线程代码运行,因此默认情况下它运行的代码(while循环)一样快,因为它可能可以在一个单一的逻辑核心。由于这大约是13%,我想你的CPU有4个超线程核心,产生8个逻辑核心。每个线程尽可能快地运行它的while循环,从而产生13%的使用率。非常简单。

不使用睡眠的副作用是整个系统运行速度较慢,并且使用/产生更多的电池/热量。

一般来说,正确的方法是给_messageQueue

bool BlockingCollection::TryTake(type& item, std::chrono::milliseconds time) 
{ 
    DWORD Ret = WaitForSingleObject(event, time.count()); 
    if (Ret) 
     return false; 
    item = Take(); //might need to use a shared function instead of calling direct 
    return true; 
} 

然后另一种方法你的循环很简单:

private void LogMessage() 
{ 
    type item; 
    while (_enabled) 
    { 
     if (_messageQueue.Take(item, std::chrono::seconds(1))) 
      ;//your origional code makes little sense, but this is roughly the same     
     processItem(itm); 
    } 
} 

这也意味着,如果一个项目的过程中可随时添加阻挡部分,它立即在上执行,而不是整整一秒后。

+0

是的,我注意到我的粉丝很快就打开了。是添加一个Thread.Sleep方法的常用解决方案?如果不是,你能指出我正确的做事方式吗? – TruthOf42

+0

@TruthOf42:添加回答 –