问题
I have a consumer as part of the producer consumer pattern:
simplified:
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);
}
}
}
}
If I remove the
Thread.Sleep(1000);
The CPU usages climbs to something extremely high (13%) as opposed to 0%, with setting the thread to sleep.
Also, if I instantiate multiple instances of the class, the CPU usage climbs in 13% increments, with each instance.
A new LogItem is added the BlockingCollection about every minute or so (maybe every 30 seconds), and writes an applicable message to a file.
Is it possible that the thread is somehow blocking other threads from running, and the system somehow needs to compensate?
Update: Updated code to better reflect actual code
回答1:
You gave the thread code to run, so by default it runs that code (the while loop) as fast as it possibly can on a single logical core. Since that's about 13%, I'd imagine your CPU has 4 hyperthreaded cores, resulting in 8 logical cores. Each thread runs it's while loop as fast as it possibly can on it's core, resulting in another 13% usage. Pretty straightforward really.
Side effects of not using sleep are that the whole system runs slower, and uses/produces SIGNIFICANTLY more battery/heat.
Generally, the proper way is to give the _messageQueue
another method like
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;
}
Then your loop is easy:
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);
}
}
It also means that if an item is added at any point during the blocking part, it's acted on immediately instead of up to a full second later.
来源:https://stackoverflow.com/questions/22051545/producer-consumer-producer-using-high-cpu