C# 使用Task.ContinueWith创建执行队列?

C# 使用Task.ContinueWith创建执行队列?,c#,task,task-queue,C#,Task,Task Queue,我有几个动作要在后台执行,但它们必须一个接一个地同步执行 我想知道使用Task.ContinueWith方法来实现这一点是否是个好主意。你预计这会有什么问题吗 我的代码如下所示: private object syncRoot =new object(); private Task latestTask; public void EnqueueAction(System.Action action) { lock (syncRoot) { if (latestT

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

我想知道使用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());
    }
}

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


就我个人而言,在这种情况下,我只会使用一个使用并发队列()的专用线程来从中提取任务-这更显式,但更容易解析阅读代码,特别是如果您想了解当前排队的任务数量等。

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

在我的应用程序中,我有数千个这些迷你队列的实例,很快发现我有内存问题。由于这些队列经常处于空闲状态,我很长时间都在保留最后一个完成的任务对象,并阻止垃圾收集。由于上一次完成的任务的结果对象通常超过85000字节,因此它被分配到大型对象堆(在垃圾收集期间不执行压缩)。这导致LOH的碎片化,并且该过程的尺寸不断增大


为了避免这种情况,您可以在锁中的实际任务之后安排一个无操作任务。对于真正的解决方案,我需要使用另一种方法来控制日程安排。

我使用了这个代码片段,并且似乎能够按照设计的方式工作。 在我的案例中,实例的数量不是几千个,而是一位数。 不过,到目前为止还没有任何问题

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


感谢您提供了一个超级简单的队列,这对我来说仍然很有效。但是从更复杂的任务队列开始,我开始使用更多的任务队列。一个改进是在ConcurrentQueue周围使用BlockingCollection。然后可以调度一个任务/工作线程,该线程只在阻塞集合上使用foreach。foreach将“挂起”,直到将新项添加到队列或对阻塞集合调用CompleteAdding()。