8

我有几个要在后台执行的操作,但它们必须一个接一个地同步执行。

我想知道使用 Task.ContinueWith 方法来实现这一点是否是个好主意。你预见到这有什么问题吗?

我的代码看起来像这样:

private object syncRoot =new object();
private Task latestTask;

public void EnqueueAction(System.Action action)
{
    lock (syncRoot)
    {
        if (latestTask == null)
            latestTask = Task.Factory.StartNew(action);
        else
            latestTask = latestTask.ContinueWith(tsk => action());
    }
}
4

3 回答 3

9

这有一个缺陷,我最近发现了自己,因为我也在使用这种方法来确保任务按顺序执行。

在我的应用程序中,我有数千个这些迷你队列的实例,并且很快发现我遇到了内存问题。由于这些队列通常是空闲的,我长时间持有最后一个完成的任务对象并阻止垃圾收集。由于最后完成任务的结果对象通常超过 85,000 字节,因此它被分配给大对象堆(在垃圾收集期间不执行压缩)。这导致了 LOH 的碎片化,并且该过程的规模不断扩大。

作为避免这种情况的一种技巧,您可以在锁内真正的任务之后安排一个无操作任务。对于真正的解决方案,我将需要采用不同的方法来控制调度。

于 2012-07-13T21:44:39.473 回答
5

这应该按设计工作(如果相应的任务已经完成,TPL 将立即安排继续)。

就我个人而言,在这种情况下,我只会使用一个使用并发队列ConcurrentQueue

于 2011-07-21T17:31:55.717 回答
0

我使用了这个片段并且似乎让它按设计工作。在我的情况下,实例的数量不会达到数千,而是个位数。尽管如此,到目前为止没有任何问题。

我会对 ConcurrentQueue 示例感兴趣,如果有的话?

谢谢

于 2014-05-09T15:21:10.613 回答