WCF中的多线程,具有准确的定时器要求

时间:2009-11-04 17:14:49

标签: c# wcf multithreading timer

我有一个WCF应用程序接受启动作业的请求。每个工作需要在X分钟(例如5分钟)之后做一些事情,也可以随时同时提出工作要求。

这就是我想到的,

// WCF class  
public class RequestManager  
{
   // WCF method
   public void StartNewJob()
   {
      // start a new thread with timer for each job?
   }
}

public class Job
{
   public Job()
   {
      // do some initializations

      // do something after x mins

      // sleep or timer?
   }

   private void DoSomething()
   {
      // do some follow-ups
   }
}

凭借我的方法,我担心会有太多线程无法为X分钟做任何事情。每秒精度也是一个要求(比如它在0:05:01开始工作,后续工作应该在0:10:01)。

最好的方法是什么?

4 个答案:

答案 0 :(得分:1)

听起来你需要Timer类的服务:

// WCF class  
public class RequestManager  
{
   // WCF method
   public void StartNewJob()
   {
      Job myJob = new Job();
      // Initialise myJob...
      myJob.Start();
   }
}

public class Job
{
    private Timer myTimer = new Timer();

    public Job()
    {
        myTimer.Elapsed += new ElapsedEventHandler(this.OnTimedEvent);
    }

    public void Start(int Miniutes)
    {
        myTimer.Interval = 60000 * Miniutes;
        myTimer.Enabled = true;
    }

    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
     // So something
    }
}

以上代码假定:

  1. 你不会做任何愚蠢的事情,比如尝试在同一个计时器实例上调用Start()两次。
  2. 应用程序中的其他位置还有一些其他非后台线程处于活动状态,导致应用程序无法关闭。
  3. 它不是一个完整的例子,但希望它能给你一个想法 - Timer类将处理保持时间而不需要为每个作业激活一个线程。

答案 1 :(得分:1)

我建议您查看RegisterWaitForSingleObject函数:

var waitObject = new AutoResetEvent(false);

// Execute the callback on a new thread 10 seconds after this call 
// and execute it only once
ThreadPool.RegisterWaitForSingleObject(
    waitObject, 
    (state, timeout) => { Console.WriteLine("ok");  }, 
    null, 
    TimeSpan.FromSeconds(10), 
    true);

// Execute the callback on a new thread 10 seconds after this call 
// and continue executing it at 10 seconds intervals until the 
// waitHandle is signaled.
ThreadPool.RegisterWaitForSingleObject(
    waitObject, 
    (state, timeout) => { Console.WriteLine("ok");  }, 
    null, 
    TimeSpan.FromSeconds(10), 
    false);

答案 2 :(得分:0)

您需要使用一些时序/调度框架,如Quartz.NET或创建自己的(轻量级)。

答案 3 :(得分:0)

对我来说,使用计时器似乎很好(也更容易实现)。

您可以在.NET中使用多个计时器类。请参阅以下文档(即使它有点老化,但似乎是一个好的开始):Comparing the Timer Classes in the .NET Framework Class Library

但是,您仍然可以通过Thread.Sleep()以及在线程唤醒和Job.DoSomethig()完成时获取时间戳来计算偏移量来实现此行为。

您可能需要仔细考虑以下事项:

  1. 执行Job.DoSomething()的线程之间的任何争论?

  2. 在以下场景中你应该非常小心:如果Job.DoSomething()有时需要超过句点(即它从0:05开始并在上面的例子中完成0:13)。这对您的应用程序意味着什么以及如何处理?

    一个。总失败 - 在0:10中止当前(0:05)执行并启动0:10执行。

    湾没什么大不了的(跳过0:10然后在0:15运行Job.DoSomething())。

    ℃。没什么大不了的,但需要在0:05任务完成后立即执行0:10执行(如果它持续超过5秒怎么办?)。

    d。即使当前正在执行0:05执行,也需要启动0:10执行。

    即其他什么?

  3. 对于您在上面选择的策略,您选择的实现(上面列出的任何计时器类或Thread.Sleep())是否都很容易支持您的策略?