C#4.0 - 间隔上的线程

时间:2011-08-06 11:50:29

标签: c# multithreading

我正在使用C#4.0。我有一段代码,我想每2-3分钟执行一次。使用4.0线程功能可以做到这一点的正确方法是什么?

6 个答案:

答案 0 :(得分:1)

使用System.Threading.Timer。

new Timer(TimerTick,null,TimeSpan.Zero,TimeSpan.FromMinutes(2));

private void TimerTick(object obj)
{
    Thread myThread =  new Thread(() => {});
    myThread.Start();
}

答案 1 :(得分:1)

最简单的方法是使用System.Threading.Timer。要记住的一件事是它会忽略你的代码正在做什么(重入)。换句话说,如果所需的时间间隔为3分钟,并且您执行的代码需要2分钟,则在此代码完成后1分钟将触发。此外,如果您的代码需要超过3分钟,那么它将被并行调用,您将不得不处理线程安全。如果这没关系,并且您不希望您的代码需要很长时间,那么您可以使用以下内容:

Timer _timer = new Timer(DoWork, "someArg", TimeSpan.Zero, TimeSpan.FromSeconds(3));

private void DoWork(object state) {
   // this code will get executed every 3 seconds:
   String argument = (String) state;
}

但是如果你想让你的计时器顺序(等待代码在开始新的间隔之前完成),你需要在每个Tick上重置它。

Timer _timer = new Timer(DoWork, "someArg", TimeSpan.Zero, TimeSpan.FromSeconds(3));

private void DoWork(object state) {
    // this code will get executed 3 seconds after the last DoWork finished
    String argument = (String)state;


    // make sure that timer will get executed in 3 seconds but will not repeat.
    // this code guarantees that timer will wait for this code to complete 
    // before starting new interval.
    _timer.Change(TimeSpan.FromSeconds(3), TimeSpan.FromMilliseconds(-1));
}

您还需要确保您的计时器实例在您仍然需要时不会收集垃圾。另请注意,.NET包含3个不同的计时器类,但您很可能需要 System.Threading.Timer 而不是 System.Windows.Forms.Timer 而不是系统。 Timers.Timer 即可。有完整的摘要here

如果您预见到更高级的计划要求(每隔一个星期一运行代码等),那么您可以使用Quartz.NET。它是一个开源的企业作业调度程序,具有许多其他功能,并且相对易于集成(参考一个dll)。

答案 2 :(得分:1)

我前段时间为无限线程处理编写了一个实用程序类。这就是....

public interface IProcessorThread
    {
        void Start();

        void Stop();
    }

    public abstract class BaseProcessorThread : IProcessorThread
    {
        protected Boolean IsRunning;
        protected readonly Thread ServiceThread;
        protected readonly Int32 PollingFrequencySeconds;

        #region Constructors

        protected BaseProcessorThread(Int32 pollingFrequencySeconds)
        {
            this.PollingFrequencySeconds = pollingFrequencySeconds;
            ServiceThread = new Thread(Process);
        }

        #endregion

        #region Protected Methods

        protected abstract void Process();

        #endregion

        #region Public Methods

        public void Start()
        {
            IsRunning = true;
            ServiceThread.Start();
        }

        public void Stop()
        {
            IsRunning = false;
            ServiceThread.Join(2000);
        }

        #endregion
    }

    public class LifetimeInfiniteThread : BaseProcessorThread
    {
        #region Fields

        private readonly Action actionMethod;
        private readonly Action<Exception> exceptionMethod;

        #endregion

        #region Constructors

        public LifetimeInfiniteThread(Int32 pollingFrequencySeconds, Action actionMethod, Action<Exception> exceptionMethod)
            : base(pollingFrequencySeconds)
        {
            this.actionMethod = actionMethod;
            this.exceptionMethod = exceptionMethod;
        }

        #endregion

        #region Protected Methods

        protected override void Process()
        {
            while (IsRunning)
            {
                try
                {
                    actionMethod.Invoke();
                }

                catch (Exception ex)
                {
                    exceptionMethod.Invoke(ex);
                }

                Thread.Sleep(PollingFrequencySeconds * 1000);
            }
        }

        #endregion
    }

<强>用法:

  static void Main(string[] args)
    {
        // Using 60 for 1 minute.
        var thread = new LifetimeInfiniteThread(60, Run, HandleException);

        thread.Start();
        Console.Read();
        thread.Stop();
    }


    static void Run()
    {
       Console.WriteLine("I m running..");
    }

    static void HandleException(Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

答案 3 :(得分:1)

一种非常简单的方法是使用Reactive Extensions

var timer = Observable.Interval(TimeSpan.FromMinutes(2));
timer.Subscribe(tick => { //execute me });

正在执行的代码将由线程池工作线程处理,因此如果它访问共享状态,您需要确保具有正确的安全防护。

答案 4 :(得分:0)

您可以使用System.Threading.Timer课程:

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

答案 5 :(得分:0)

使用计时器的解决方案:

public class Worker : IDisposable
{
    private readonly System.Threading.Timer _timer;
    private readonly int PeriodInMs = (int)TimeSpan.FromMinutes(2).TotalMilliseconds;

    public Worker()
    {
        _timer = new System.Threading.Timer(_ => OnTick(), null, Timeout.Infinite, Timeout.Infinite);
    }

    public void Start()
    {
        _timer.Change(0, PeriodInMs);
    }

    public void Stop()
    {
        _timer.Change(Timeout.Infinite, Timeout.Infinite);
    }

    private void OnTick()
    {
        _timer.Change(Timeout.Infinite, Timeout.Infinite);
        try
        {
            //Your work goes here
        }
        finally
        {
            _timer.Change(PeriodInMs, PeriodInMs);
        }
    }

    public void Dispose()
    {
        _timer.Dispose();
    }
}