C#X秒后执行动作 [英] C# execute action after X seconds

查看:244
本文介绍了C#X秒后执行动作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要开发出一个给定的时间后定期执行一个动作一个Windows控制台应用程序。我在什么地方读到一个Timer类是仅适用于Windows窗体应用程序,那么,什么是完成我想要的东西的最佳方式?


解决方案

原始邮件:我写了这个示例控制台应用程序(使用C#
4.0 [由默认参数指示])。这是非常灵活和利用的操作授人以允许通过您要执行使用定时类(在
的System.Threading)
片段。重载的不要的方法在静态
类不计算拖延的时间所有的跑腿。你
可以选择有剪断通过指定间隔(
毫秒)重复。当然,你可以修改以接受重复间隔时间跨度
的方法。




三年前提供的控制台应用实例已被证明很受欢迎的人寻找这种性质的东西。许多询问的问题处理工作进度管理。我参加了一个尝试写,可以相当简单实现一个新的类。它仅提供作为使用的一个例子。对于那些谁认为我的风格是劣质或充满了不必要的代码,这是由我的罚款。它是由你来调整它为您的编程风格,实施规范等。



对类以下的变化使它更可用:




  • DO()方式创造就业机会的工作原理类似于老班。 的(类型的对象的)已经提供了一个额外的可选参数,让你指定作业的名称。这个名字会让你修改以前的计划作业(请继续阅读)。

  • 实例化的定时的对象类中的内部保持让你有多个计划任务,可以通过名称引用独立。

  • 新的处理程序已经添加了作业管理(使用键)。它们由 SuspendJob() GetJobFor() ENDJOB() ResumeJob 方法。<规定/ LI>
  • 静态构造函数订阅到的 AppDomain.CurrentDomain.DomainUnload 的事件为解构处置任何正在运行的作业时的AppDomain(应用程序)正在卸载。

  • 参数检查已被添加到确保参数的期望是什么。

  • 作用域锁定,您可以从任何线程增加就业机会。



没有改变的?




  • 的例子仍然没有按' T柄在操作委托的结果。如果你需要更好的东西,实现它。 :)



向下滚动,找到新的实现类。 !享受






**旧的控制台类,如下所示:**

 使用系统; 
使用的System.Threading;

命名ConsoleApplication1
{
///<总结>
///,管理在未来某个时候任务的执行类。
///< /总结>
公共静态类在
{
#地区的会员

///<总结>
///指定将被解雇执行延迟匿名方法的方法。
///< /总结>
私人只读静态TimerCallback定时器=新TimerCallback(At.ExecuteDelayedAction);

#endregion

#地区的方法

///<总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///< PARAM NAME =延时→延的周期在执行前等待< /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态无效DO(行动行动,时间跨度延迟,INT间隔= Timeout.Infinite)
{
//创建一个新的线程计时器延迟
新后执行的方法定时器(定时器,动作,Convert.ToInt32(delay.TotalMilliseconds),间隔);

的回报;
}

///<总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///< PARAM NAME =延迟>延迟的时间(毫秒)在执行前等待< /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态无效DO(行动行动,诠释延迟,INT间隔= Timeout.Infinite)
{
执行(动作,TimeSpan.FromMilliseconds(延迟),间隔);

的回报;
}

///<总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///&下; PARAM NAME =duetime参数>在该方法中需要执行的到期时间和所述; /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态无效DO(行动行动,日期duetime参数,INT间隔= Timeout.Infinite)
{
如果(duetime参数< DateTime.Now)
{
罚球新ArgumentOutOfRangeException(duetime参数,指定适当的时候已经过去了。);
}

执行(动作,duetime参数 - DateTime.Now,间隔);

的回报;
}

///<总结>
///一个执行特定的时间间隔后,延迟操作方法。
///< /总结>
///< PARAM NAME =O>该行动代表了要执行< /参数>
///<说明方式>该方法被调用自己的线程< /言论>
私有静态无效ExecuteDelayedAction(对象o)
{
//调用匿名方法
(O作为行动).Invoke();

的回报;
}

#endregion
}

类节目
{
静态无效的主要(字串[] args)
{
Console.WriteLine(时间:{0} - 开始,DateTime.Now);

//表明,顺序无关
At.Do(()=> Console.WriteLine(时间:{0} - 的Hello World(5S后),日期时间。现在),DateTime.Now.AddSeconds(5));
At.Do(()=> Console.WriteLine(时间:{0} - 的Hello World(3S后),DateTime.Now),DateTime.Now.AddSeconds(3));
At.Do(()=> Console.WriteLine(时间:{0} - 的Hello World(1秒后),DateTime.Now),DateTime.Now.AddSeconds(1));

At.Do

()=>
{
//证明匿名方法
灵活性(INT I = 0;我小于10;我++)
{
Console.WriteLine(时间:{0} - 世界您好 - 我== {1}(后4S!),DateTime.Now,我);
}
},
TimeSpan.FromSeconds(4)
);

//阻塞主线程来显示后台线程
Thread.sleep代码执行(100000);

的回报;
}
}
}






**新的类提供如下:**

 使用系统; 
使用System.Linq的;
使用的System.Threading;
使用System.Collections.Generic;

命名空间实用程序
{
///<总结>是一个指定的
///间隔后设计的基于动作的执行匿名委托
类///。该类还支持间隔重复的任务。
///< /总结>
公共静态类在
{
#地区的嵌入式类

///<总结>
///嵌入式常见的类定义在工作周期。
///< /总结>
公共静态课时
{
#地区的会员

///<总结>
///指定的对象,表示不重新启动。
///< /总结>
公共静态只读时间跨度DoNotStart = TimeSpan.FromMilliseconds(-1.0);

///<总结>
///指定一个对象,该指示立即开始。
///< /总结>
公共静态只读时间跨度,立即= TimeSpan.FromMilliseconds(0.0);

///<总结>
///指定一秒的间隔。
///< /总结>
公共静态只读时间跨度SecondsOne = TimeSpan.FromSeconds(1.0);

///<总结>
///指定五秒的间隔。
///< /总结>
公共静态只读时间跨度SecondsFive = TimeSpan.FromSeconds(5.0);

///<总结>
///指定十五秒的间隔。
///< /总结>
公共静态只读时间跨度SecondsFifteen = TimeSpan.FromSeconds(15.0);

///<总结>
///指定三十秒的时间间隔。
///< /总结>
公共静态只读时间跨度SecondsThirty = TimeSpan.FromSeconds(30.0);

///<总结>
///指定的100毫秒的间隔。
///< /总结>
公共静态只读时间跨度MicroDelay = TimeSpan.FromMilliseconds(100);

#endregion
}

#endregion

#地区的会员

///<总结> ;
///指定可用于同步的对象。
///< /总结>
私人只读静态对象SyncRoot上;

///<总结>
///指定基于区间执行创建的Timer对象的集合。
///< /总结>
///<&言论GT;
///我们必须在集合中保留这些以阻止GC定时器处置。
///< /言论>
私人只读静态字典<对象,定时器和GT; ActiveTimers;

///<总结>
///指定创建定时器时的时间戳的集合。
///< /总结>
私人只读静态字典<对象,日期> TimerCreation;

///<总结>
///指定的对象,将产生的伪随机数。
///< /总结>
私人只读静态随机RNG;

#endregion

#地区的静态构造函数

静在()
{
SyncRoot上=新的对象();

ActiveTimers =新词典<对象,定时器和GT;();
TimerCreation =新词典<对象,日期>();

RNG =新的随机();

//解构
AppDomain.CurrentDomain.DomainUnload + =新的EventHandler(CurrentDomain_DomainUnload);

的回报;
}

///<总结>
///用于此对象使用清理资源的方法。
///< /总结>
静态无效CurrentDomain_DomainUnload(对象发件人,EventArgs五)
{
//处理所有定时器直接
At.ActiveTimers.Values.ToList()的ForEach(A => ; a.Dispose());

的回报;
}

#endregion

#地区的方法

#地区在招聘临时

/// <总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///< PARAM NAME =延时→延的周期在执行前等待< /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态定时器DO(?动作动作,时间跨度延迟,时间跨度onInterval = NULL,对象键= NULL)
{
定时定时器;

如果(键== NULL)
{
//自动生成密钥
键= string.Concat(自动(At.RNG。 NextNonNegativeLong(),));
}

锁(At.ActiveTimers)
{
//行动 - 包含我们要调用
At.ActiveTimers.Add方法(键,定时器=新定时器(ActionInvoker,动作,延时,onInterval ?? At.Periods.DoNotStart));
At.TimerCreation.Add(键,DateTime.Now);
}

//Log.Message
//(
// LogMessageType.Debug,
//[DEBUG] {0}:注册在作业(键= {1},初始延迟= {2},间隔= {3}),
//动作,
//键,
//延迟,
//(onInterval == NULL)从不:onInterval.Value.ToString()
//);

返回定时器;
}

///<总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///< PARAM NAME =延迟>延迟的时间(毫秒)在执行前等待< /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态定时器DO(行动行动,诠释延迟,INT间隔= Timeout.Infinite,对象键= NULL)
{
返回DO(动作,TimeSpan.FromMilliseconds(延迟),时间跨度。 FromMilliseconds(间隔),键);
}

///<总结>
///一个执行的延迟时间后,一个匿名方法的方法。
///< /总结>
///&下; PARAM NAME =动作>需要被执行的匿名方法&下; /参数>
///&下; PARAM NAME =duetime参数>在该方法中需要执行的到期时间和所述; /参数>
///< PARAM NAME =间隔>在时间(毫秒)再次执行匿名方法(Timeout.Infinite禁用)之前延迟< /参数>
公共静态定时器DO(行动行动,日期duetime参数,INT间隔= Timeout.Infinite,对象键= NULL)
{
如果(duetime参数< DateTime.Now)
{
抛出新ArgumentOutOfRangeException(duetime参数,指定适当的时候已经过去了。);
}

返回DO(动作,duetime参数 - DateTime.Now,TimeSpan.FromMilliseconds(间隔),键);
}

#endregion

#地区在招聘检索

///<总结>
///试图对一个给定键检索作业(Timer对象)方法。
///< /总结>
///< PARAM NAME =键>也就是说我们得到一份工作的关键< /参数>
公共静态定时器GetJobFor(对象键)
{
如果(键== NULL)
{
抛出新的ArgumentNullException(钥匙);
}

锁(At.ActiveTimers)
{
如果(At.ActiveTimers.ContainsKey(键)==假)
{
/ *
Log.Message

LogMessageType.Error,
[错误]在({0}):无法找到指定键的工作,

);
* /
返回NULL;
}

返回At.ActiveTimers [关键]
}
}

///<总结>
///重圆工作,并删除与它相关联的所有资源的方法。
///< /总结>
///< PARAM NAME =键>也就是说我们得到一份工作的关键< /参数>
公共静态无效ENDJOB(对象键)
{
定时定时器;

如果((定时器= GetJobFor(密钥))== NULL)
{
//没有计时器 - 不能暂停
的回报;
}

//处置计时器对象
timer.Dispose的();

锁(At.ActiveTimers)
{
//从字典
At.ActiveTimers.Remove取出存在(键);
/ *
Log.Message

LogMessageType.Info,
[INFO]在({0}):作业已被处理(创建{1} ,持续时间{2}),
键,
TimerCreation [关键] .ToISODateTime(),
(DateTime.Now - TimerCreation [关键])ToText()
) ;
* /
At.TimerCreation.Remove(键);
}

的回报;
}

///<总结>
///试图暂停主动的工作(使用所提供的密钥)方法。
///< /总结>
///< PARAM NAME =键>也就是说我们得到一份工作的关键< /参数>
公共静态无效SuspendJob(对象键)
{
定时定时器;

如果((定时器= GetJobFor(密钥))== NULL)
{
//没有计时器 - 不能暂停
的回报;
}

//设置定时不重新启动
timer.Change(TimeSpan.FromMilliseconds(-1),TimeSpan.FromMilliseconds(-1));
/ *
Log.Message

LogMessageType.Info,
[INFO]在({0}):作业已停止,

);
* /
的回报;
}

///<总结>
///试图恢复活动作业(使用所提供的密钥)方法。
///< /总结>
///< PARAM NAME =键>也就是说我们得到一份工作的关键< /参数>
///< PARAM NAME =延时→延的重新启动作业之前量(指定< B> 0℃; / B>到立即重新启动)LT; /参数>
///< PARAM NAME =间隔>间隔之间的延迟(指定< B> -1ms< / B>到防止间隔)。< /参数>
公共静态无效ResumeJob(对象键,时间跨度延迟,时间跨度间隔)
{
定时定时器;

如果((定时器= GetJobFor(密钥))== NULL)
{
//没有计时器 - 不能暂停
的回报;
}

//设置定时不重新启动
timer.Change(延迟,间隔);
/ *
Log.Message

LogMessageType.Info,
[INFO]在({0}):作业已重新开始(延迟= {1 },间隔= {2}),
键,
延迟,
区间
);
* /
的回报;
}

#endregion

///<总结>
///上的计时器调用一个动作委托方法。
///< /总结>
///< PARAM NAME =O>将参考这是将要采取的动作< /参数>
私有静态无效ActionInvoker(对象o)
{
//调用委托
(O作为行动).Invoke();

的回报;
}

#endregion
}
}


I want to develop a windows console application which executes an action periodically after a given time. I've read somewhere that a timer class is only available for windows forms applications, so what is the best way to accomplish what I want?

解决方案

Original message: I wrote this sample console application (using C# 4.0 [as indicated by the default parameters]). It's extremely versatile and utilizes the Action delegate to allow passing snippets that you want executed using the Timer class (in System.Threading). The overloaded Do method of the At static class does all the legwork of computing the interval of delay. You can optionally have the snipped repeated by specifying an interval (in milliseconds). You can of course modify the method to accept TimeSpan for the repeat interval.

The console application example provided three years ago has proven pretty popular for folks looking for something of this nature. Many of the questions asked dealt with job schedule management. I took a crack at writing a new class that can be implemented fairly simply. It's provided only as an example of use. For those who believe my style is inferior or riddled with unnecessary code, that's fine by me. It's up to you to tweak it for your programming style, implementation practices, etc.

The following changes to the class make it more usable:

  • Creating jobs with the Do() method works similarly as the old class. An additional optional parameter key (type object) has been provided to let you specify the name of a job. This name will let you modify previously scheduled jobs (keep reading).
  • Instantiated Timer objects are kept internally within the class allowing you to have multiple scheduled tasks that can be referenced by name individually.
  • New handlers have been added for job management (using the key). They are provided by the SuspendJob(), GetJobFor(), EndJob(), and ResumeJob methods.
  • Static constructor subscribes to the AppDomain.CurrentDomain.DomainUnload event for the "deconstructor" to dispose any running jobs when the appdomain (application) is unloading.
  • Parameter checking has been added to make sure parameters are what is expected.
  • Scoped locking allows you to add jobs from any thread.

What hasn't changed?

  • The example still doesn't handle the result of the Action delegate. If you need something better, implement it. :)

Scroll down to find the new implementation of the class. Enjoy!


** The old console class as follows: **

using System;
   using System.Threading;

   namespace ConsoleApplication1
   {
  /// <summary>
  /// Class that manages the execution of tasks sometime in the future.
  /// </summary>
  public static class At
  {
     #region Members

     /// <summary>
     /// Specifies the method that will be fired to execute the delayed anonymous method.
     /// </summary>
     private readonly static TimerCallback timer = new TimerCallback(At.ExecuteDelayedAction);

     #endregion

     #region Methods

     /// <summary>
     /// Method that executes an anonymous method after a delay period.
     /// </summary>
     /// <param name="action">The anonymous method that needs to be executed.</param>
     /// <param name="delay">The period of delay to wait before executing.</param>
     /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
     public static void Do(Action action, TimeSpan delay, int interval = Timeout.Infinite)
     {
        // create a new thread timer to execute the method after the delay
        new Timer(timer, action, Convert.ToInt32(delay.TotalMilliseconds), interval);

        return;
     }

     /// <summary>
     /// Method that executes an anonymous method after a delay period.
     /// </summary>
     /// <param name="action">The anonymous method that needs to be executed.</param>
     /// <param name="delay">The period of delay (in milliseconds) to wait before executing.</param>
     /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
     public static void Do(Action action, int delay, int interval = Timeout.Infinite)
     {
        Do(action, TimeSpan.FromMilliseconds(delay), interval);

        return;
     }

     /// <summary>
     /// Method that executes an anonymous method after a delay period.
     /// </summary>
     /// <param name="action">The anonymous method that needs to be executed.</param>
     /// <param name="dueTime">The due time when this method needs to be executed.</param>
     /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
     public static void Do(Action action, DateTime dueTime, int interval = Timeout.Infinite)
     {
        if (dueTime < DateTime.Now)
        {
           throw new ArgumentOutOfRangeException("dueTime", "The specified due time has already elapsed.");
        }

        Do(action, dueTime - DateTime.Now, interval);

        return;
     }

     /// <summary>
     /// Method that executes a delayed action after a specific interval.
     /// </summary>
     /// <param name="o">The Action delegate that is to be executed.</param>
     /// <remarks>This method is invoked on its own thread.</remarks>
     private static void ExecuteDelayedAction(object o)
     {
        // invoke the anonymous method
        (o as Action).Invoke();

        return;
     }

     #endregion
  }

  class Program
  {
     static void Main(string[] args)
     {
        Console.WriteLine("Time: {0} - started", DateTime.Now);

        // demonstrate that order is irrelevant
        At.Do(() => Console.WriteLine("Time: {0} - Hello World! (after 5s)", DateTime.Now), DateTime.Now.AddSeconds(5));
        At.Do(() => Console.WriteLine("Time: {0} - Hello World! (after 3s)", DateTime.Now), DateTime.Now.AddSeconds(3));
        At.Do(() => Console.WriteLine("Time: {0} - Hello World! (after 1s)", DateTime.Now), DateTime.Now.AddSeconds(1));

        At.Do
        (
           () =>
           {
              // demonstrate flexibility of anonymous methods
              for (int i = 0; i < 10; i++)
              {
                 Console.WriteLine("Time: {0} - Hello World! - i == {1} (after 4s)", DateTime.Now, i);
              }
           },
           TimeSpan.FromSeconds(4)
        );

        // block main thread to show execution of background threads
        Thread.Sleep(100000);

        return;
     }
  }
   }


** The new class is provided as follows: **

using System;
using System.Linq;
using System.Threading;
using System.Collections.Generic;

namespace Utility
{
   /// <summary>
   /// Class that is designed to execution Action-based anonymous delegates after a specified
   /// interval.  This class also supports repetitive tasks on an interval.
   /// </summary>
   public static class At
   {
      #region Embedded Classes

      /// <summary>
      /// Embedded class definition for common At job periods.
      /// </summary>
      public static class Periods
      {
         #region Members

         /// <summary>
         /// Specifies an object that indicates to not restart.
         /// </summary>
         public static readonly TimeSpan DoNotStart = TimeSpan.FromMilliseconds(-1.0);

         /// <summary>
         /// Specifies an object that indicates to start immediately.
         /// </summary>
         public static readonly TimeSpan Immediately = TimeSpan.FromMilliseconds(0.0);

         /// <summary>
         /// Specifies an interval of one second.
         /// </summary>
         public static readonly TimeSpan SecondsOne = TimeSpan.FromSeconds(1.0);

         /// <summary>
         /// Specifies an interval of five seconds.
         /// </summary>
         public static readonly TimeSpan SecondsFive = TimeSpan.FromSeconds(5.0);

         /// <summary>
         /// Specifies an interval of fifteen seconds.
         /// </summary>
         public static readonly TimeSpan SecondsFifteen = TimeSpan.FromSeconds(15.0);

         /// <summary>
         /// Specifies an interval of thirty seconds.
         /// </summary>
         public static readonly TimeSpan SecondsThirty = TimeSpan.FromSeconds(30.0);

         /// <summary>
         /// Specifies an interval of 100ms.
         /// </summary>
         public static readonly TimeSpan MicroDelay = TimeSpan.FromMilliseconds(100);

         #endregion
      }

      #endregion

      #region Members

      /// <summary>
      /// Specifies an object that can be used for synchronization.
      /// </summary>
      private readonly static object syncRoot;

      /// <summary>
      /// Specifies a collection of Timer object that were created for interval-based execution.
      /// </summary>
      /// <remarks>
      /// We must keep these in a collection to prevent the GC from disposing of the timers.
      /// </remarks>
      private readonly static Dictionary<object, Timer> ActiveTimers;

      /// <summary>
      /// Specifies a collection of timestamps of when timers are created.
      /// </summary>
      private readonly static Dictionary<object, DateTime> TimerCreation;

      /// <summary>
      /// Specifies an object that will produce pseudo-random numbers.
      /// </summary>
      private readonly static Random RNG;

      #endregion

      #region Static Constructor

      static At()
      {
         syncRoot = new object();

         ActiveTimers = new Dictionary<object, Timer>();
         TimerCreation = new Dictionary<object, DateTime>();

         RNG = new Random();

         // "deconstructor"
         AppDomain.CurrentDomain.DomainUnload += new EventHandler(CurrentDomain_DomainUnload);

         return;
      }

      /// <summary>
      /// Method used to cleanup resources used by this object.
      /// </summary>
      static void CurrentDomain_DomainUnload(object sender, EventArgs e)
      {
         // dispose of all the timers directly
         At.ActiveTimers.Values.ToList().ForEach(a => a.Dispose());

         return;
      }

      #endregion

      #region Methods

      #region At Job Staging

      /// <summary>
      /// Method that executes an anonymous method after a delay period.
      /// </summary>
      /// <param name="action">The anonymous method that needs to be executed.</param>
      /// <param name="delay">The period of delay to wait before executing.</param>
      /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
      public static Timer Do(Action action, TimeSpan delay, TimeSpan? onInterval = null, object key = null)
      {
         Timer timer;

         if (key == null)
         {
            // auto-generate a key
            key = string.Concat("Auto(", At.RNG.NextNonNegativeLong(), ")");
         }

         lock (At.ActiveTimers)
         {
            // action - contains the method that we wish to invoke
            At.ActiveTimers.Add(key, timer = new Timer(ActionInvoker, action, delay, onInterval ?? At.Periods.DoNotStart));
            At.TimerCreation.Add(key, DateTime.Now);
         }

         //Log.Message
         //(
         //   LogMessageType.Debug,
         //   "[DEBUG] {0}: registered At job (key = {1}, initial delay = {2}, interval = {3})",
         //   action,
         //   key,
         //   delay,
         //   (onInterval == null) ? "never" : onInterval.Value.ToString()
         //);

         return timer;
      }

      /// <summary>
      /// Method that executes an anonymous method after a delay period.
      /// </summary>
      /// <param name="action">The anonymous method that needs to be executed.</param>
      /// <param name="delay">The period of delay (in milliseconds) to wait before executing.</param>
      /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
      public static Timer Do(Action action, int delay, int interval = Timeout.Infinite, object key = null)
      {
         return Do(action, TimeSpan.FromMilliseconds(delay), TimeSpan.FromMilliseconds(interval), key);
      }

      /// <summary>
      /// Method that executes an anonymous method after a delay period.
      /// </summary>
      /// <param name="action">The anonymous method that needs to be executed.</param>
      /// <param name="dueTime">The due time when this method needs to be executed.</param>
      /// <param name="interval">The period (in milliseconds) to delay before executing the anonymous method again (Timeout.Infinite to disable).</param>
      public static Timer Do(Action action, DateTime dueTime, int interval = Timeout.Infinite, object key = null)
      {
         if (dueTime < DateTime.Now)
         {
            throw new ArgumentOutOfRangeException("dueTime", "The specified due time has already elapsed.");
         }

         return Do(action, dueTime - DateTime.Now, TimeSpan.FromMilliseconds(interval), key);
      }

      #endregion

      #region At Job Retrieval

      /// <summary>
      /// Method that attempts to retrieve a job (Timer object) for a given key.
      /// </summary>
      /// <param name="key">The key that we are getting a job for.</param>
      public static Timer GetJobFor(object key)
      {
         if (key == null)
         {
            throw new ArgumentNullException("key");
         }

         lock (At.ActiveTimers)
         {
            if (At.ActiveTimers.ContainsKey(key) == false)
            {
               /*
               Log.Message
               (
                  LogMessageType.Error,
                  "[ERROR] At({0}): unable to find a job with specified key",
                  key
               );
               */
               return null;
            }

            return At.ActiveTimers[key];
         }
      }

      /// <summary>
      /// Method that ends a job and removes all resources associated with it.
      /// </summary>
      /// <param name="key">The key that we are getting a job for.</param>
      public static void EndJob(object key)
      {
         Timer timer;

         if ((timer = GetJobFor(key)) == null)
         {
            // no timer - cannot suspend
            return;
         }

         // dispose of the timer object
         timer.Dispose();

         lock (At.ActiveTimers)
         {
            // remove the existence from the dictionary
            At.ActiveTimers.Remove(key);
            /*
            Log.Message
            (
               LogMessageType.Info,
               "[INFO] At({0}): job has been disposed (created {1}, duration {2})",
               key,
               TimerCreation[key].ToISODateTime(),
               (DateTime.Now - TimerCreation[key]).ToText()
            );
            */
            At.TimerCreation.Remove(key);
         }

         return;
      }

      /// <summary>
      /// Method that attempts to suspend an active job (using the provided key).
      /// </summary>
      /// <param name="key">The key that we are getting a job for.</param>
      public static void SuspendJob(object key)
      {
         Timer timer;

         if ((timer = GetJobFor(key)) == null)
         {
            // no timer - cannot suspend
            return;
         }

         // set the timer to not restart
         timer.Change(TimeSpan.FromMilliseconds(-1), TimeSpan.FromMilliseconds(-1));
         /*
         Log.Message
         (
            LogMessageType.Info,
            "[INFO] At({0}): job has been suspended",
            key
         );
         */
         return;
      }

      /// <summary>
      /// Method that attempts to resume an active job (using the provided key).
      /// </summary>
      /// <param name="key">The key that we are getting a job for.</param>
      /// <param name="delay">The amount of delay before restarting the job (specify <b>0</b> to restart immediately).</param>
      /// <param name="interval">The delay between intervals (specify <b>-1ms</b> to prevent intervals).</param>
      public static void ResumeJob(object key, TimeSpan delay, TimeSpan interval)
      {
         Timer timer;

         if ((timer = GetJobFor(key)) == null)
         {
            // no timer - cannot suspend
            return;
         }

         // set the timer to not restart
         timer.Change(delay, interval);
         /*
         Log.Message
         (
            LogMessageType.Info,
            "[INFO] At({0}): job has been resumed (delay = {1}, interval = {2})",
            key,
            delay,
            interval
         );
         */
         return;
      }

      #endregion

      /// <summary>
      /// Method that invokes an action delegate on a timer.
      /// </summary>
      /// <param name="o">A reference to the action that is to be taken.</param>
      private static void ActionInvoker(object o)
      {
         // invoke the delegate
         (o as Action).Invoke();

         return;
      }

      #endregion
   }
}

这篇关于C#X秒后执行动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆