我有一个可以排队完全不同类型的工作的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来管理工作人员从队列中取出工作但是我仍然需要自己管理队列,因为还有更多工作,而不是一次性加载到内存中)
答案 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个作业。)