0
public class JobRunner
{
    internal Timer Timer;
    internal readonly IEnumerable<YuartzJob> Jobs;

    public void Start()
    {
        this.Timer = new Timer(5000);
        this.Timer.Elapsed += Timer_Elapsed;
        this.Timer.Start();
    }

    public void Stop()
    {
        this.Timer.Stop();
    }

    internal void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        foreach (var job in Jobs)
        {
            MyActivator.RunJob(job);
        }
    }
}

public class MyActivator
{
    public static void RunJob(YuartzJob job)
    {
        var objectHandle = Activator.CreateInstance(job.AssemblyName, job.ClassName).Unwrap();
        var currentJob = (IJob)objectHandle;
        currentJob.Run();
    }
}

在我使用 MyActivator.RunJob(job) 的地方我应该怎么做:

  1. 我应该使用 ThreadPool 调用 MyActivator.RunJob 吗?
  2. 我应该使用 Threads 调用 MyActivator.RunJob 吗?
  3. 我应该使用 BackgroundWorker 调用 MyActivator.RunJob 吗?
  4. 它是否以这种方式工作而不做任何事情?
4

3 回答 3

3

如果您的目标是 .NET 4,最简单的方法是使用任务。任务使用 ThreadPool 中的线程执行方法。.NET 运行时(实际上是一个 TaskScheduler)确保线程池不会被太多任务耗尽:

    foreach (var job in Jobs)
    {
        Task.Factory.StartNew(()=>MyActivator.RunJob(job));
    }

任务还允许轻松取消、异常处理和链接,这在使用 ThreadPool 或您自己的线程时是不可能的。

对于早期版本,您应该首先考虑 ThreadPool,并且仅在作业太多且运行时间长以至于它们有耗尽线程池的风险时才创建自​​己的线程:

    foreach (var job in Jobs)
    {
        ThreadPool.QueueUserWorkItem(o=>MyActivator.RunJob(job));
    }

Backgroundworker 在 .NET 4+ 中被认为是过时的,并且无论如何只适用于非常粗粒度的并行性。在您的情况下,您必须为每个作业创建一个单独的工作人员,订阅其事件,运行它并在它之后进行清理。

于 2012-06-22T08:46:24.450 回答
2

如果您想有效地并行处理一组项目,我的首选将是专门为此目的而制作的:Parallel.ForEach().

在内部,它使用Tasks,这意味着它将在ThreadPool. 它还尝试Task有效地使用 s,所以如果你有一个包含一百万个项目的集合,它不会创建一百万个Tasks。

于 2012-06-22T09:38:50.757 回答
-1

.NET Framework 提供了四个计时器。其中两个是通用多线程定时器:

  • System.Threading.Timer
  • System.Timers.Timer

另外两个是专用的单线程定时器:

  • System.Windows.Forms.Timer(Windows 窗体计时器)
  • System.Windows.Threading.DispatcherTimer(WPF 计时器)

因此,如果您希望您的方法以多线程方式/并行执行,那么您必须选择前两个中的一个。

在此处查找有关此内容的更多信息以及示例源代码

于 2012-06-22T08:46:14.420 回答