7

我正在运行这段代码,它使用了相当多的 CPU,尽管它大部分时间都没有做任何事情。

while (this.IsListening)
{
    while (this.RecievedMessageBuffer.Count > 0)
    {
        lock (this.RecievedMessageBuffer)
        {
            this.RecievedMessageBuffer[0].Reconstruct();
            this.RecievedMessageBuffer[0].HandleMessage(messageHandler);
            this.RecievedMessageBuffer.RemoveAt(0);
        }
    }
}

在满足条件之前阻止的最佳方法是什么?

4

3 回答 3

10

使用WaitHandle.

WaitHandle waitHandle = new AutoResetEvent();

// In your thread.
waitHandle.WaitOne();

// In another thread signal that the condition is met.
waitHandle.Set();

您还可以考虑更改类的接口以在要读取新数据时引发事件。然后,您可以将代码放入事件处理程序中。

于 2012-06-11T05:14:51.683 回答
7

假设您使用的是 .NET 4,我建议切换RecievedMessageBufferBlockingCollection。当您将消息放入其中时,调用它的Add方法。当你想检索消息时,调用它的TakeTryTake方法。Take 将阻止读取线程,直到消息可用,而不会像原始示例那样烧毁 CPU。

// Somewhere else
BlockingCollection<SomethingLikeAMessage> RecievedMessageBuffer = new BlockingCollection<SomethingLikeAMessage>();


// Something like this where your example was
while (this.IsListening)
{
    SomethingLikeAMessage message;
    if (RecievedMessageBuffer.TryTake(out message, 5000);
    {
        message.Reconstruct();
        message.HandleMessage(messageHandler);
    }
}
于 2012-06-11T05:20:23.620 回答
2

以上代码行,特别是 AutoResetEvent 在版本 3.5 中可用。所以像上面这样简单的代码加上一些小的修正是非常有效的,因为它可以工作并且接近基础 API。更正应该是

AutoResetEvent waitHandle = new AutoResetEvent(false); 具有参数 false 的构造函数使 WaitOne() 等待,因为 AutoResetEven 未重置 (false)。使用接口 WaitHandle 并没有太大的优势,所以我将只使用 AutoResetEvent 来代替,因为它公开了 Set 方法,而 WaitOne 在这种情况下非常冗长。最重要的是,构造函数参数应该是假的。

于 2014-12-29T16:24:32.320 回答