以FIFO-ish方式管理多个队列的最佳方法

时间:2012-06-26 09:37:21

标签: .net queue .net-4.5 job-scheduling

我有一个可以排队完全不同类型的工作的UI。目前,它通过将作业存储在数据库中的相应表(Table-per-JobType)

中来实现

然后我的后端进程出现,拿起工作,并假设有一个可用的工作者(线程),使用它来执行适当的工作方法。

在PseudoCode中:

While(Runnning) {
    While(Queue1.HasJobs && Workers.IdleCount > 0) {
        FirstIdleWorker.Execute(Queue1Method(Type1Job));
    }

    ...

    While(QueueN.HasJobs && Workers.IdleCount > 0) {
        FirstIdleWorker.Execute(QueueNMethod(TypeNJob));
    }
    //Wait for a job to complete or a polling timeout if queues are empty
}

(实际上并不是那么天真,但它说明了处理工作的顺序)

正如你所看到的,这可行,但它没有考虑添加了什么订单作业。这不是一个交易破坏者,因为工作是原子的,但从UI的角度来看很烦人 - 例如用户1排队类型2的20个作业,然后是用户2排队1,000个类型1的作业。用户1现在必须等待所有用户2的作业完成,然后才能处理(相对)快速作业。

作业确实有一个CreatedOn属性,因此确定顺序并不困难,但如何以强烈的方式实现组合队列而不是意大利面条代码呢?

我正在尝试避免使用.CreatedOn.Queue1Id.Queue2Id.Queue3Id的“GenericJob”对象,因为这只是感觉很草率。

虽然FIFO大体上是我所追求的,但这并不是一个严格的要求 - 我只是不希望项目永远被碰撞。

这种事情有这种模式吗?如果没有,有人可以指点我一个好的教程吗?

(顺便说一句,这些都是潜在的长期工作。我实际上在幕后使用TPL来管理工作人员从队列中取出工作但是我仍然需要自己管理队列,因为还有更多工作,而不是一次性加载到内存中)

2 个答案:

答案 0 :(得分:1)

如果我错了,请告诉我,我希望这个伪代码解释界面抽象没问题。

界面可能如下所示:

enum JobTypes
{
    JobType1 = 0x01,
    JobType2 = 0x02,
    JobType3 = 0x03
}
interface IJob
{
    int ID { get; set; }
    JobTypes JobType { get; set; }
    DateTime Date { get; set; }
    bool Complete { get; set; }
    void Process(List<object> parameters);
}

每个作业类型处理器都实现此界面,更改和添加属性以满足您的需求:

class JobType1 : IJob
{
    public int ID { get; set; }
    public JobTypes JobType { get; set; }
    public DateTime Date { get; set; }
    public bool Complete { get; set; }
    public void Process(List<object> parameters)
    {
        throw new NotImplementedException();
    }
}

然后,您可以将作业类型混合到一个列表中:

List<IJob> joblist = new List<IJob>();

并且可能使用lambda按日期对它们进行排序:

joblist.Sort((a, b) => DateTime.Compare(a.Date, b.Date));

获取未处理作业的列表(不检查忙处理*)

List<IJob> undone = joblist.Where(job => job.Complete == false) as List<IJob>;

答案 1 :(得分:1)

完整的答案可能类似于作业车间调度,因为您的工作需要不同的资源或资源水平,并且您希望避免使短期工作挨饿。它有点复杂并需要一些阅读,但它最终的工作要少于尝试从单个队列中进行复杂的调度。

听起来好像你在作业之间存在依赖关系,所以省力的方法是每个作业的每个用户类型,然后在队列上进行加权循环。 (即,从队列Y中为队列Y中的每个作业从队列X中获取2个作业。)