这是要求。
我有一个作业/任务,它将一个参数作为输入并执行一些功能。
我需要使用不同的输入参数在不同的计划时间执行方法DoWork。可以说, 在下午1点,必须使用input1触发DoWork。 在下午1点30分,DoWork必须通过input2触发。 在下午3点,DoWork必须通过input3触发。 ....
这是最好的方法吗? - 使用System.Timer - 使用System.Threading.Timer - 使用TaskFactory&的TaskScheduler
无论我到目前为止尝试过什么,首先都有Windows服务:
public partial class MainJobExecWS : ServiceBase
{
private Timer taskTimer;
public MainJobExecWS()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
// Define Timer for MainJob
TimeSpan dueTime = // define starting time of timer;
TimeSpan repeatingPeriod = // define repeating interval of timer;
MainJob jm = new MainJob();
TimerCallback tcb = jm.executeMainJob;
taskTimer = new Timer(tcb, null, dueTime, repeatingPeriod);
base.OnStart(args);
}
protected override void OnStop()
{
if (taskTimer != null)
{
taskTimer.Dispose();
}
base.OnStop();
}
}
主要工作的定义:
class MainJob
{
public void executeMainJob(object state)
{
// Main Job Definition
}
private void scheduleChildJob()
{
String childJobInput = "abc"; // How to pass this input to the child job????
TimeSpan execTimeSpan = // define the timespan for triggering child job;
ChildJobDef chdJob = new ChildJobDef();
TimerCallback tcb = chdJob.executeChildJob;
Timer timer = new Timer(tcb, null, execTimeSpan, ?); // How to specify that the child job should be triggered only once??
}
}
最后是Child Job Definition的定义:
class ChildJobDef
{
public void executeChildJob(object state)
{
// How to get the input sent to this job???
}
}
答案 0 :(得分:1)
我发现Reactive Extensions最好地处理这些场景,因为它们的IScheduler
接口允许您安排在特定的绝对时间运行的操作(而不是指定相对延迟)。他们的调度程序非常强大,可以补偿时钟漂移,系统时间的变化等等。
使用它们很简单:
DateTimeOffset startTime = /* determine start time */;
Scheduler.Default.Schedule(startTime, () => RunTask1());
答案 1 :(得分:0)
我很无聊所以我把一个使用System.Timers.Timer
的演示程序放在一起,安排任务在特定时间的下一个实例运行:
public class ScheduledTask<T>
{
private T _parameter;
private Action<T> _action;
private Timer _timer;
public ScheduledTask( T parameter, Action<T> action, int hour, int minute, int second )
{
Debug.Assert( null != parameter && null != action, "Arg(s) == null" );
_parameter = parameter;
_action = action;
_timer = new Timer( GetIntervalForTimeOfDay( hour, minute, second ) )
{
AutoReset = false
};
_timer.Elapsed += ( sender, e ) =>
{
if( null != TaskStarted )
{
TaskStarted( this, new DateTimeEventArgs( DateTime.Now ) );
}
action( _parameter );
if( null != TaskCompleted )
{
TaskCompleted( this, new DateTimeEventArgs( DateTime.Now ) );
}
};
_timer.Start();
}
public static double GetIntervalForTimeOfDay( int hour, int minute, int second )
{
Debug.Assert( hour <= 23 && hour >= 0 && minute <= 59 && minute >= 0 && second <= 59 && second >= 0, "Parameter(s) out of range" );
var now = DateTime.Now;
var interval = ( new DateTime( now.Year, now.Month, now.Day, hour, minute, second ) )
.Subtract( now )
.TotalMilliseconds;
if( 0.0 > interval )
{
interval += 24.0 * 60.0 * 60.0 * 1000.0; // hours in day * minutes in hour * seconds in minute * milliseconds in minute
}
return interval;
}
public event EventHandler<DateTimeEventArgs> TaskStarted;
public event EventHandler<DateTimeEventArgs> TaskCompleted;
}
public class DateTimeEventArgs : EventArgs
{
public DateTime DateTime { get; private set; }
public DateTimeEventArgs( DateTime dt )
{
DateTime = dt;
}
}
用法:
class Program
{
static void Main()
{
Console.WriteLine( "App started: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
var st1 = new ScheduledTask<int>( 1, i =>
{
System.Threading.Thread.Sleep( 1000 );
Console.WriteLine( "{0}: {1:yyyy-MM-dd HH:mm:ss}", i, DateTime.Now );
}, 15, 30, 0 ); // 3:30:00 PM
st1.TaskStarted += ( sender, e ) => Console.WriteLine( "1 started: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
st1.TaskCompleted += ( sender, e ) => Console.WriteLine( "1 completed: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
var st2 = new ScheduledTask<int>( 2, i =>
{
System.Threading.Thread.Sleep( 1000 );
Console.WriteLine( "{0}: {1:yyyy-MM-dd HH:mm:ss}", i, DateTime.Now );
}, 15, 51, 7 ); // 3:51:07 PM
st2.TaskStarted += ( sender, e ) => Console.WriteLine( "2 started: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
st2.TaskCompleted += ( sender, e ) => Console.WriteLine( "2 completed: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
Console.WriteLine( "App thread paused: {0:yyyy-MM-dd HH:mm:ss}", DateTime.Now );
Console.ReadLine();
}
}