您的位置:首页 > 编程语言 > C#

C#中如何控制缓冲空间的上限

2007-12-31 22:35 260 查看
我们用C#基于“生产者/消费者”编程时,往往会用Queue、Hashtable或 Dictionary 泛型类型来作一个缓存,用于缓存“生产者”产生的数据,若“消费者”能及时处理这些数据,倒不成问题,但若某种原因,导致“消费者”没有及时处理,就可能导致内存被大量消耗,系统性能急剧下降,直到失去响应。如何有效地限制缓冲空间的上限?由于我们的“生产者”与“消费者”可能分别为多个线程,因此不能采用简单加锁的方式来解决,而是使用ManualResetEvent 或AutoResetEvent来实现线程间的消息传递。 解决方案如下代码所示:

/// <summary>
/// 这个例子用于演示如例控制一个缓冲的大小
/// 此例中以一个队列为类,假定元素成员总数不得大于100个
/// </summary>
public class BufferManager
{
public Queue<int> buffer = new Queue<int>();
private System.Threading.ManualResetEvent ev = new System.Threading.ManualResetEvent(false);

/// <summary>
/// 将对象添加到 Queue 的结尾处,模拟生产者。 Queue 的容量是指 Queue 可以保存的元素数。随着向 Queue 中添加元素,容量通过重新分配按需自动增加。
/// 测试证明,如果不加限制地添加,可能会导致内存大量被占用,甚至系统停止响应
/// </summary>
/// <param name="item"></param>
public void Enqueue(int item)
{
if (buffer.Count > 99)
{
//若缓冲大于99个成员,则阻塞线程
ev.WaitOne();
}
lock (buffer)
{
buffer.Enqueue(item);
//向队列(缓冲)添加一个元素后,判断一下元素个数是否已达上限,若已达上限,则发出阻塞通知
if (buffer.Count > 99)
{
ev.Reset();
}
}
}

/// <summary>
/// 从 Queue 的开头移除的对象。模拟消费者。
/// </summary>
public void Dequeue()
{
if (buffer.Count > 0)
{
lock (buffer)
{
buffer.Dequeue();
//从队列(缓冲取出一个元素后,通知被阻塞的线程继续)
ev.Set();
}

}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: