C# 使用具有优先级的多线程的作业调度器
我即将启动一个C#.NET 4.0项目,该项目将创建一个作业调度器C# 使用具有优先级的多线程的作业调度器,c#,multithreading,scheduled-tasks,scheduling,scheduler,C#,Multithreading,Scheduled Tasks,Scheduling,Scheduler,我即将启动一个C#.NET 4.0项目,该项目将创建一个作业调度器 作业没有截止日期,并且可能运行时间很长,最长可达天 该工作有3个优先级:空闲、正常、关键;从最低到最高 正在不断创建新的工作 具有较高优先级的较新作业应优先于优先级较低的作业,即使旧作业已创建很长时间 每个作业都将由一个长时间运行的线程处理 工作是重新进入的。作业的状态将持久化到数据库中,因此可以随时暂停作业或终止作业线程 我的计划是使用信号量,并将并发条目的数量设置为系统核心的数量。将为队列中的每个作业创建一个新线程,并且所有
也就是说,我可能不会用信号灯来做这个。虽然它可以工作,但单个计数器(通过联锁的.Increment/decreation管理)和ManualResetEvent也可以工作,而且重量要轻得多。好吧,我更倾向于下面这样的东西 首先,启动所需的所有线程:
for(int i=0; i < Environment.ProcessorCount; i++)
{
Thread t = new Thread(RunWork);
// setup thread
t.Start();
threads.Add(t);
}
然后创建一个队列管理对象。这显然会变得更复杂,因为它可能需要与您的数据库同步,等等
class MyQueue<TJob> where TJob : ITask
{
Queue<TJob> high, med, low;
bool GetNextJob(ref TJob work)
{
if(work.Priority == PriorityType.High && !work.Complete)
return true;
lock(this)
{
if(high.Count > 0)
{
Enqueue(work);//requeue to pick back up later
work = high.Dequeue();
return true;
}
if(work.Priority == PriorityType.Med && !work.Complete)
return true;
if(med.Count > 0)
{
Enqueue(work);//requeue to pick back up later
work = med.Dequeue();
return true;
}
if(!work.Complete)
return true;
if(low.Count > 0)
{
work = low.Dequeue();
return true;
}
work = null;
return false;
}
void Enqueue(TJob work)
{
if(work.Complete) return;
lock(this)
{
else if(work.Priority == PriorityType.High) high.Enqueue(work);
else if(work.Priority == PriorityType.Med) med.Enqueue(work);
else low.Enqueue(work);
}
}
}
有一个很棒的框架从Java移植到了C#看看吧
嗯,我的调度方案完全基于优先级,某些作业需要根据新作业的到达而停止。quartz.net能帮我吗?不确定是否停止正在运行的作业,但quartz.net确实具有基于优先级的处理。在我看来,使用信号量似乎是任务并行库实现的信号。TPL和信号量不是很有效吗?第三方物流给你很大的控制权。高优先级作业将排队(例如,索引0)向下推低优先级作业。此时,TPL将允许您暂停最低优先级的作业。。。???或者我误解了什么…@IAbstract:TPL可能非常有用,尽管它没有任何内置的“暂停”,而且语义电话的使用实际上与TPL是分开的……对,有很多实现细节遗漏了……我不确定TPL中是否真的有暂停。但是,我确信可以保持作业的状态,本质上是暂停任务。:)这太棒了,不知怎的,我觉得这可能就是我想要的。你能告诉我什么是数据类型吗?我没有看到WorkReadyHandle在MyQueue类的任何地方定义。我遗漏了什么吗?一般来说,我不熟悉C。关机是一个
线程
或手动重置事件
——很可能是一个线程。我仍然更喜欢TPL而不是手动线程管理,尤其是因为引用了.Net 4。TPL对长时间运行的线程是否有效,这可能会持续几天?我预计_shutdown和workready handle是手动重置事件,我可能会将shutdown和workready句柄都放在MyQueue类中,然后直接访问它们。是否需要一次关闭一个线程取决于您。
class MyQueue<TJob> where TJob : ITask
{
Queue<TJob> high, med, low;
bool GetNextJob(ref TJob work)
{
if(work.Priority == PriorityType.High && !work.Complete)
return true;
lock(this)
{
if(high.Count > 0)
{
Enqueue(work);//requeue to pick back up later
work = high.Dequeue();
return true;
}
if(work.Priority == PriorityType.Med && !work.Complete)
return true;
if(med.Count > 0)
{
Enqueue(work);//requeue to pick back up later
work = med.Dequeue();
return true;
}
if(!work.Complete)
return true;
if(low.Count > 0)
{
work = low.Dequeue();
return true;
}
work = null;
return false;
}
void Enqueue(TJob work)
{
if(work.Complete) return;
lock(this)
{
else if(work.Priority == PriorityType.High) high.Enqueue(work);
else if(work.Priority == PriorityType.Med) med.Enqueue(work);
else low.Enqueue(work);
}
}
}
public void RunWork()
{
ITask job;
while(!_shutdown.WaitOne(0))
{
if(queue.GetNextJob(ref job))
job.PerformOneUnitOfWork();
else
WaitHandle.WaitAny(new WaitHandle[] { _shutdown, queue.WorkReadyHandle });
}
}