问题
I am implementing an asynchronous buffer system where I want exactly one consumer of a queue to guarantee that items are processes in order. The consumer should check the queue periodically, process all items in it, and then "Sleep" for some interval. Task.Delay() seems perfect for such a system, since unlike Thread.Sleep() it won't consume a thread while sleeping and unlike Timer it won't launch a new thread if processing the queue items takes longer than the sleep interval. However, I'm wondering if using Task.Delay() in a while loop will create a memory leak if the task system is tracking the entire continuation list for the original task. For reference, my system looks like:
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();
回答1:
It won't cause a memory leak, however if you are in a tight loop you may want to dispose the tasks rather than waiting for their finalizer
e.g.
var t = Task.Delay(interval);
await t.ConfigureAwait(false);
t.Dispose();
But you probably don't want to, and shouldn't need to (see Do I need to dispose of Tasks? )
回答2:
I am implementing an asynchronous buffer system...
I strongly suggest you use an existing one. TPL Dataflow is my top recommendation. But if that's not available on your platform, then my AsyncProducerConsumerQueue is an option.
This setup allows your consumer to just use ReceiveAsync
/DequeueAsync
and no Task.Delay
is necessary.
That said, I don't believe there would be a memory leak like the one you describe. I have not actually run it in a profiler to verify this, though.
来源:https://stackoverflow.com/questions/20705025/does-a-loop-with-task-delay-create-a-memory-leak