我有需要大量的初始化(一个结实的机器上1-2秒)的对象。 尽管一旦被初始化,只需要大约20毫秒做一个典型的“工作”
为了防止它被重新初始化每一个应用程序想要使用它的时候(可能是50次,第二次或不是为典型的使用分钟),我决定给它一个作业阙,并让它运行在自己的线程,检查,看看是否有在阙它的任何工作。 但我不完全知道如何使该带或不带工作indefinetly运行的线程。
这是我到目前为止,任何批评是值得欢迎
private void DoWork()
{
while (true)
{
if (JobQue.Count > 0)
{
// do work on JobQue.Dequeue()
}
else
{
System.Threading.Thread.Sleep(50);
}
}
}
左思右想:我想我可能需要杀死这个线程优雅INSEAD让它永远运行下去的,所以我想我会添加一个工作类型,它告诉线程结束。 如何结束这样一个线程的任何想法也表示赞赏。
你需要 lock
,所以你可以Wait
和Pulse
:
while(true) {
SomeType item;
lock(queue) {
while(queue.Count == 0) {
Monitor.Wait(queue); // releases lock, waits for a Pulse,
// and re-acquires the lock
}
item = queue.Dequeue(); // we have the lock, and there's data
}
// process item **outside** of the lock
}
与加样:
lock(queue) {
queue.Enqueue(item);
// if the queue was empty, the worker may be waiting - wake it up
if(queue.Count == 1) { Monitor.PulseAll(queue); }
}
你可能也想看看这个问题 ,这限制了队列的大小(阻塞,如果它太满)。
你需要一个同步原语,就像一个WaitHandle的 (看静态方法)。 这样,您就可以“信号”的工作线程有工作。 它检查队列和工作时保持,直到队列为空,此时它等待互斥再次表示它。
使工作项目之一是quit命令了,所以,你可以通知工作线程时,它的时间才能退出线程
在大多数情况下,我已经做到了这一点颇为相似,你怎么设置 - 但不能同日而语。 我有一个数据结构(在Python),直到将项目放入队列,否定了睡眠通话的需求,这将阻止线程工作的优势。
如果.NET提供这样的一类,我会考虑使用它。 线程阻塞比睡眠呼叫的线程旋转好得多。
你可以通过该任务可以为“零”一样简单; 如果代码收到null,它知道它的时间打出来的而回家。
如果你并不真的需要有线程退出(和只是希望它从保持你的应用程序运行保持),您可以设置Thread.IsBackground为true,它会结束时,所有非后台线程结束。 威尔和马克都具有处理队列好的解决办法。
抓住并行框架 。 它有一个BlockingCollection <T> ,你可以作为一个作业队列使用。 你怎么会使用它:
- 创建BlockingCollection <T>,将保留您的任务/作业。
- 创建一些线程其中有一个永无休止的循环(而(真){//获取作业从队列中)
- 设置线程去
- 新增职位,收集来的时候,他们提供
直到项目出现在集合中的线程将被阻止。 谁的把它是会得到它(取决于CPU)。 现在我用这个和它的伟大工程。
它也有依靠MS多个线程访问同一资源来编写代码,特别讨厌位的优势。 每当你可以得到别人写的,你应该去了。 假设,当然,他们有更多的技术/测试资源和比你的经验相结合。
我已经实现了一个后台任务队列,不使用任何类型的while
循环,或脉冲,或等待,或事实上,触摸Thread
的所有对象。 它似乎工作。 (我指的是它已经在生产环境中处理数千个任务,每天在过去18个月中没有任何异常行为。)这两个显著属性的类,一个Queue<Task>
和BackgroundWorker
。 有三种方法显著,这里简称:
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (TaskQueue.Count > 0)
{
TaskQueue[0].Execute();
}
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Task t = TaskQueue[0];
lock (TaskQueue)
{
TaskQueue.Remove(t);
}
if (TaskQueue.Count > 0 && !BackgroundWorker.IsBusy)
{
BackgroundWorker.RunWorkerAsync();
}
}
public void Enqueue(Task t)
{
lock (TaskQueue)
{
TaskQueue.Add(t);
}
if (!BackgroundWorker.IsBusy)
{
BackgroundWorker.RunWorkerAsync();
}
}
这并不是说没有等待和脉冲。 但是,这一切都发生在内部BackgroundWorker
。 这只是唤醒每当一个任务队列中的下降,一直持续到队列为空,然后就回去睡觉。
我决不是在线程方面的专家。 是否有一个原因与周围乱七八糟System.Threading
像这样的问题,如果使用BackgroundWorker
会做什么?