【发布时间】:2014-01-09 09:33:55
【问题描述】:
我正在实现一个异步缓冲系统,我希望队列中只有一个消费者来保证项目是按顺序处理的。消费者应该定期检查队列,处理其中的所有项目,然后“睡眠”一段时间。 Task.Delay() 似乎非常适合这样的系统,因为与 Thread.Sleep() 不同,它在睡眠时不会消耗线程,并且与 Timer 不同,如果处理队列项花费的时间超过睡眠间隔,它不会启动新线程.但是,我想知道如果任务系统正在跟踪原始任务的整个延续列表,在 while 循环中使用 Task.Delay() 是否会造成内存泄漏。作为参考,我的系统如下所示:
void EnqueueItem(Item item) {
lock (this._lock) { this._items.Add(item); }
}
async Task Consumer() {
while (true) {
await Task.Delay(interval).ConfigureAwait(false);
Item[] items = null;
lock (this._lock) {
if (this._disposed) { return; }
if (this._items.Count > 0)
{
items = this._items.ToArray();
this._items.Clear();
}
}
if (items != null) { Process(items); }
}
}
// in the constructor of the buffer
this.Consumer();
【问题讨论】:
-
我之前使用过计时器方法,现在只使用
Monitor.TryEnter方法。如果它无法获得锁,它可以直接退出该方法而不做任何事情。这意味着可能会创建一个线程,但它不会存在很长时间。或者,您可以在每个流程循环的开始和结束时停止和启动计时器。 -
一旦任务完成并且您的代码删除任务对象引用,任务的延续列表将自动被垃圾收集。 Task.Delay 对此没有任何影响,除了让任务运行的时间超过可能需要的时间。
-
与您的问题无关,但是如果您从构造函数中调用
Consumer(),当Process()抛出异常时会发生什么? -
@svick 在实际代码中,正是出于这个原因,Process() 调用被包装在 try-catch 中(错误记录在 catch 中)
标签: c# task async-await