需要反馈线程代码

时间:2009-02-14 19:35:52

标签: c# multithreading

以下是某些人想在生产应用中使用的代码(不是我,诚实) - 我想要一些独立的反馈意见。

 public class JobProcessor<TJob> : IJobProcessor<TJob> where TJob : class
 {
  private readonly IJobQueue<TJob> theJobQueue =
   new NullQueue<TJob>();

  private Thread processorThread;

  private bool shutdownRequested;

  private readonly IJobObserver<TJob> theObserver = new NullObserver<TJob>();

  public AutoResetEvent threadStartedEvent = new AutoResetEvent(false);

  private int processorThreadId = 0;

  private volatile TJob currentJob = null;

  public JobProcessor(IJobQueue<TJob> jobQueue, IJobObserver<TJob> observer)
  {
   if (observer != null)
   {
    theObserver = observer;
   }
   shutdownRequested = false;
   theJobQueue = jobQueue;
   CreateAndRunThread();
  }

  private void CreateAndRunThread()
  {
   processorThread = new Thread(Run)
                      {
                       Name = "Tpk Processor Thread", IsBackground = true
                      };
   processorThread.SetApartmentState(ApartmentState.STA);
   processorThread.Priority = ThreadPriority.BelowNormal;
   processorThread.Start();
  }

  public void Shutdown()
  {
   threadStartedEvent.WaitOne();

   shutdownRequested = true;

   theJobQueue.Interrupt(processorThreadId);
  }

  public TJob CurrentJob()
  {
   return currentJob;
  }

  private void Run()
  {
   processorThreadId = Thread.CurrentThread.ManagedThreadId;

   threadStartedEvent.Set();

   while (!BufferClearedAndShutDown())
   {
    try
    {
     ProcessNextMessage();
    }
    catch (ThreadAbortException)
    {
     CreateAndRunThread();
     break;
    }
    catch (Exception e)
    {  }
   }
  }

  private void ProcessNextMessage()
  {
   currentJob = theJobQueue.RetrieveJob();
   if (currentJob != null)
   {
    theObserver.ProcessMessage(this, currentJob);
   }
   currentJob = null;
  }

  private bool BufferClearedAndShutDown()
  {
   return theJobQueue.IsEmpty && shutdownRequested;
  }
 }
}

5 个答案:

答案 0 :(得分:2)

您是否尝试捕获ThreadAbortException然后重新创建自己?我不确定这是可能的,但无论如何,这不是一个很好的方式来玩操作系统。

如果在currentJob = theJobQueue.RetrieveJob()之后发生异常,你将失去工作;但在theObserver.ProcessMessage(this,currentJob)之前;

除非你的jobQueue是线程安全的,否则你应该在访问它时添加锁定。

答案 1 :(得分:2)

这只是一个生产者/消费者队列吗?有很多预先推出的例子 - 我几天前在这里发布了一个例子(但我现在找不到它)...这样说 - 我发布的版本是很多更简单 - 即“显然没有错误”,而不是“没有明显的错误”。我会看看能不能找到它......

(编辑:found it

重点是;在该版本中,工作线程只是:

T item;
while(queue.TryDequeue(out item)) {
    // process item
}
// queue has been closed and drained

答案 2 :(得分:1)

在不知道IJobQueue,IJobObserver或IJobProcessor的语义的情况下很难给出有用的反馈,但这里有一些突出的细节:

  1. processorThread似乎并不真正需要;可以/应该只是CreateAndRunThread中的本地
  2. shutdownRequested应标记为volatile,在将shutdownReqeusted设置为true后调用Thread.MemoryBarrier(),或使用Thread.VolatileWrite设置shutdownRequested字段
  3. 为什么在要求它关闭之前等待线程启动?
  4. 不知道你为什么需要一个threadStartedEvent,它用于什么?特别是公开它是有点可怕的
  5. 不知道如何实施IJobQueue.Interrupt,很难说是否存在问题
  6. 谁使用CurrentJob,为什么?感到风险
  7. 虽然捕获自己的ThreadAbortException会捕获大多数情况,但它不会捕获所有内容。您可以使用一个单独的监视器线程,它调用Thread.Join,并在双重检查后,BufferClearedAndShutdown()调用CreateAndRunThread()

答案 3 :(得分:0)

代码中缺少很多上下文,但id就像在上面添加我的2便士,我同意。

在Randy的第2项中,我只使用锁定语句而不是内存屏障,这是MSDN推荐的方法,除非您在盒子上使用多个Itanium CPU(内存排序较弱)

http://msdn.microsoft.com/en-us/library/system.threading.thread.memorybarrier.aspx

我完全同意第6项。公开方法将裁判公开给职业队中的某个项目?那不是很好吗?,特别是当你讨论线程安全时,如果你需要从这个暴露给外部世界的类中获得一些信息,那就让它变成不可变的并且暴露出来。更好的封装。

答案 4 :(得分:0)

既然有些人已经回答我觉得在不偏袒任何人的情况下添加我自己的评论是安全的: - )

  1. 为什么要在关闭之前等待线程启动?
  2. 记录线程ID并将其用作识别哪个线程可以将其关闭的方法?
  3. currentJob标记为volatile但不是shutdownRequested(并且未在锁定中设置)
  4. 为什么要将一个队列+一个工人混合在一起?为什么不将队列分开,然后使用一个或多个线程。
  5. 我想不出为什么他会期待一个ThreadAbortException,以便抛弃当前的工作线程并创建一个新线程。
  6. 尽管代码顶部有关于如何简单地扩展类以使用多个工作线程的注释,但我认为这种设计根本不容易转移到多个工作线程(与队列的方法不同) /工人是分开的。)
  7. 我不是多线程大师或任何其他所以我想发布它只是为了确保不仅仅是我认为这段代码看起来有点狡猾。