当前位置: 动力学知识库 > 问答 > 编程问答 >

multithreading - Scheduling Job in .NET using Threads & Timers

问题描述:

This is the requirement.

I have job/task which takes one parameter as input and performs some function.

I need to execute the method DoWork at different schedule timings with different input parameter. Lets say,

at 1 PM, DoWork has to be triggered with input1.

at 1.30 PM, DoWork has to be triggered with input2.

at 3 PM, DoWork has to be triggered with input3.

....

Which is the best way to do this??

- Using System.Timer

- Using System.Threading.Timer

- Using TaskFactory & TaskScheduler

Whatever I tried so far, first of all there is a Windows Service:

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();

}

}

Definition for the Main Job:

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??

}

}

And finally the definition for Child Job Definition:

class ChildJobDef

{

public void executeChildJob(object state)

{

// How to get the input sent to this job???

}

}

网友答案:

I find the Reactive Extensions handle these scenarios best, as their IScheduler interface lets you to schedule actions to run at a specific, absolute time (as opposed to specifying a relative delay). Their schedulers are fairly robust, and will compensate for clock drift, changes to system time, etc.

Using them is easy:

DateTimeOffset startTime = /* determine start time */;
Scheduler.Default.Schedule(startTime, () => RunTask1());
网友答案:

I was bored so I threw together a demo of using System.Timers.Timer to schedule a task to run at the next instance of a specific time:

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;
    }
}

Usage:

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();
    }
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: