none
How to perfectly schedule a task at specified time. RRS feed

  • Question

  • Hi,

    I recently posted on the below post and they solved my problem as the app is running well,

    but a user called "Cor Ligthert" who proposed me that solution said that I'm not supposed to use that code in production !!!

    Not sure why??  just wanna know if there's another alternative such as library or something else to use instead of his code.

    www.social.msdn.microsoft.com/Forums/vstudio/en-US/1bc71779-4b08-4d85-aaf1-531ed836a008/how-to-run-task-on-specified-timer-from-list-of-structure?forum=vbgeneral


    • Edited by Christine25 Monday, September 18, 2017 6:37 PM
    Monday, September 18, 2017 6:36 PM

Answers

  • @ leshay.

    I searched in Google for a VB. Net example but couldn't find.

    Can you please provide me with a small sample of code that works?

    doing it this way means you don't need your own application to be running for a task to be activated.

    What do you mean? so you mean, my app can be closed but the task will still perform...

    Hi

    Check out THIS link. May be helpful.

    When I said 'you don't need your own application to be running for a task to be activated.', I meant that if you build an appliction to create/add/edit/remove Task Scheduler Tasks, then once a Task has been added, when the trigger time is reached, whether or not your appliction is running, the Task will activate.

    Example: say you crested a Task from your applicstion to run a programme at 06:00 tomorrow, then at that time, with your application not running, the Task will trigger and run the programme.

    In other words, you can build an application to manage your own Tasks, but the system Task Scheduler handles everything else.

    *

    EDIT: added this example code from one of many in the above link.

    Imports Microsoft.Win32.TaskScheduler Module Module1 Sub Main() Using ts As New TaskService() ' Create a new task definition and assign properties Dim td As TaskDefinition = ts.NewTask td.RegistrationInfo.Description = "Does something" ' Add a trigger that will, starting tomorrow, fire every other week on Monday ' and Saturday and repeat every 10 minutes for the following 11 hours Dim wt As New WeeklyTrigger() wt.StartBoundary = DateTime.Today.AddDays(1) wt.DaysOfWeek = DaysOfTheWeek.Monday Or DaysOfTheWeek.Saturday wt.WeeksInterval = 2 wt.Repetition.Duration = TimeSpan.FromHours(11) wt.Repetition.Interval = TimeSpan.FromMinutes(10) td.Triggers.Add(wt) ' Add an action (shorthand) that runs Notepad

    ' NOTE: edit for your own Path to a text file. td.Actions.Add(New ExecAction("notepad.exe", "c:\test.log")) ' Register the task in the root folder ts.RootFolder.RegisterTaskDefinition("Test", td) End Using End Sub End Module



    Regards Les, Livingston, Scotland






    • Edited by leshay Wednesday, September 20, 2017 5:04 PM
    • Marked as answer by Christine25 Thursday, August 15, 2019 10:28 AM
    Wednesday, September 20, 2017 4:36 PM

All replies

  • An alternate (and I don't have a code sample but use the following for awhile in a Windows service) is using System.Threading.Timer. When creating the Timer you pass in a call-back/delegate. In the delegate do the work then dispose of the Timer. Prior to the above you call the Change (this is overloaded) with time to start, if using the overload Change(Int32,Int32) the first parameter is how long to wait from "now", passing Timeout.Infinity is suggested in your case for the 2nd parameter.

    If you want the timer to run the next day, in the delegate (indicated above) dispose then re-create the timer.

    The above is a lot to take in and will take time to first start up date math for the first parameter of the Timer so be patient.


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    Monday, September 18, 2017 7:02 PM
    Moderator
  • Hi,

    I recently posted on the below post and they solved my problem as the app is running well,

    but a user called "Cor Ligthert" who proposed me that solution said that I'm not supposed to use that code in production !!!

    Not sure why??  just wanna know if there's another alternative such as library or something else to use instead of his code.

    www.social.msdn.microsoft.com/Forums/vstudio/en-US/1bc71779-4b08-4d85-aaf1-531ed836a008/how-to-run-task-on-specified-timer-from-list-of-structure?forum=vbgeneral


    It comes down to this: Do you want reasonably good scheduling or thread synchronization?

    I tried to explain last time that you'll come down to making that choice but you cut me off without notice - so good luck with it all, but what I said there really is the issue because it can't (or may not be) both.

    If your handling of the event takes longer than the cycle, then you'll need to make the decision of which way to go and you'll need code that can handle it either way.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Monday, September 18, 2017 8:03 PM
  • Thanks.

    @ Frank L. Smith

    First off, Sorry about the last time.

    Do you want reasonably good scheduling or thread synchronization?

    not sure what to say? I don't know !

    Please maybe if you can explain me when does an application need "Good scheduling" or "thread synchronization" in order for me to know which one should I go for?

    cause my app stores each task in xml file including its schedule and run the schedule at the specified time.

    So several tasks can be run at same time (that definitely needs Multithreading) if the user planned it.

    Basically, my app is like Windows task scheduler.





    • Edited by Christine25 Tuesday, September 19, 2017 5:31 PM
    Tuesday, September 19, 2017 5:30 PM
  • Hi

    Why not use the Microsoft.Win32.TaskScheduler. You can set/add/remove tasks and don't have to worry about threading, indeed, doing it this way means you don't need your own application to be running for a task to be activated.


    Regards Les, Livingston, Scotland


    • Edited by leshay Tuesday, September 19, 2017 5:39 PM
    Tuesday, September 19, 2017 5:38 PM
  • Thanks.

    @ Frank L. Smith

    First off, Sorry about the last time.

    Do you want reasonably good scheduling or thread synchronization?

    not sure what to say? I don't know !

    Please maybe if you can explain me when does an application need "Good scheduling" or "thread synchronization" in order for me to know which one should I go for?

    cause my app stores each task in xml file including its schedule and run the schedule at the specified time.

    So several tasks can be run at same time (that definitely needs Multithreading) if the user planned it.

    Basically, my app is like Windows task scheduler.





    Just call me Frank please. When I see my whole name in print (other than by me), I feel like I'm in the third grade and got called to the principal's office all over again. ;-)

    *****

    I'll jump ahead and say that if you need your program to do multiple things at once, you'll definitely need to get into multi-threading. You might also want to look at task-based asynchronous programming. I think that ultimately that will be the solution here but I'll jump back and explain the issue(s):

    If you're dealing with a Windows.Forms timer, it's STA so when the event is raised, it's by definition on one single thread. Whatever you do in that event handler method prevents that timer from continuing until it returns.

    A System.Timers.Timer isn't like that. Like I said last time, it's a wrapper for the Threading timer. It's MTA so by definition, the .Elapsed event is raised on a thread from the threadpool. In that regard it will keep up the period quite precisely but there's an issue: How do you take that and get it back to your program without creating a CrossThreadingException?

    The way to do that is with a Synchronizing object but when you give it, for example, a reference to your form (with the "Me" keyword), you've solved the issue of it not being raised on the threadpool so no cross-thread exception, but we're sort of in the same place now as the form's timer: What to do with the amount of time it takes for your method to return?

    The way that I've gotten around that in the past is that in a class library that I created, I gave myself a property where I could have it figure out how long that took and skip it.

    That's confusing I'm sure, but in mine, it "ticked" every one second and I was using it as a countdown timer.

    If I never intruded on that "tick", it would maintain that one second pretty closely, but if my code did anything at all when that event is raised - because of the synchronizing object - it stalled it. I ensured that it stalled it because the only other option would be that the event were on another thread.

    To get around it, I had it "make up the number of ticks" that it should have been (but was stalled).

    *****

    Inside my class, the following two methods are at the heart of it:

        Private Sub _
            InternalTimerTick(ByVal sender As Object, _
                              ByVal e As ElapsedEventArgs)
    
            Try
                If System.Threading.Interlocked.CompareExchange(_synch, 1, 0) = 0 Then
    
                    ' Process the data here:
    
                    If _syncToElapsedTime Then
                        _tickCount += 1
                        _heartbeatsSkipped = Math.Abs(CInt(_operationSW.Elapsed.TotalSeconds) - _tickCount)
                        _currentCount = _totalSecondsToCountDown - CInt(_operationSW.Elapsed.TotalSeconds)
                    Else
                        _currentCount -= 1
                    End If
    
                    If _currentCount <= 0 Then
                        _currentCount = 0
                    End If
    
                    _loopCountSW.Stop()
    
                    Dim offset As Decimal = CDec(1 - _loopCountSW.Elapsed.TotalSeconds)
                    _heartBeatInterval += offset
    
                    _loopCountSW.Restart()
    
                    _synch = 0
    
                    OnTickTock()
                Else
                    Threading.Thread.Sleep(1)
                End If
    
            Catch ex As Exception
                Dispose()
                _operationSW.Stop()
                _operationException = ex
            End Try
    
    
    
            If _currentCount = 0 Then
                _operationSW.Stop()
                Dispose()
    
                OnComplete()
            Else
                If _preventReEntrance Then
                    SetupTimer()
                End If
            End If
    
        End Sub
    
        Private Sub SetupTimer()
    
            Dispose()
    
            _heartBeat = New System.Timers.Timer
            AddHandler _heartBeat.Elapsed, AddressOf InternalTimerTick
    
            With _heartBeat
                If _synchObject IsNot Nothing Then
                    .SynchronizingObject = CType(_synchObject, System.ComponentModel.ISynchronizeInvoke)
                End If
    
                .Interval = _heartBeatInterval
                .AutoReset = Not _preventReEntrance
                .Enabled = True
            End With
    
        End Sub

    CompareExchange doesn't prevent re-entrance; it's just used to detect it. In what I ended up doing, it's impossible anyway but I left that in it. You can read more about it here:

    https://docs.microsoft.com/en-us/dotnet/standard/threading/interlocked-operations

    Dealing with re-entrancy and making the decisions about what to do can drive you insane. Dig into the details in-depth and set up some test projects before you commit to any of it.

    For what it's worth...


    "A problem well stated is a problem half solved.” - Charles F. Kettering




    • Edited by Frank L. Smith Tuesday, September 19, 2017 6:23 PM ...typos
    Tuesday, September 19, 2017 6:06 PM
  • @ leshay.

    I searched in Google for a VB. Net example but couldn't find.

    Can you please provide me with a small sample of code that works?

    doing it this way means you don't need your own application to be running for a task to be activated.

    What do you mean? so you mean, my app can be closed but the task will still perform...

    Wednesday, September 20, 2017 4:16 PM
  • @ leshay.

    I searched in Google for a VB. Net example but couldn't find.

    Can you please provide me with a small sample of code that works?

    doing it this way means you don't need your own application to be running for a task to be activated.

    What do you mean? so you mean, my app can be closed but the task will still perform...

    Hi

    Check out THIS link. May be helpful.

    When I said 'you don't need your own application to be running for a task to be activated.', I meant that if you build an appliction to create/add/edit/remove Task Scheduler Tasks, then once a Task has been added, when the trigger time is reached, whether or not your appliction is running, the Task will activate.

    Example: say you crested a Task from your applicstion to run a programme at 06:00 tomorrow, then at that time, with your application not running, the Task will trigger and run the programme.

    In other words, you can build an application to manage your own Tasks, but the system Task Scheduler handles everything else.

    *

    EDIT: added this example code from one of many in the above link.

    Imports Microsoft.Win32.TaskScheduler Module Module1 Sub Main() Using ts As New TaskService() ' Create a new task definition and assign properties Dim td As TaskDefinition = ts.NewTask td.RegistrationInfo.Description = "Does something" ' Add a trigger that will, starting tomorrow, fire every other week on Monday ' and Saturday and repeat every 10 minutes for the following 11 hours Dim wt As New WeeklyTrigger() wt.StartBoundary = DateTime.Today.AddDays(1) wt.DaysOfWeek = DaysOfTheWeek.Monday Or DaysOfTheWeek.Saturday wt.WeeksInterval = 2 wt.Repetition.Duration = TimeSpan.FromHours(11) wt.Repetition.Interval = TimeSpan.FromMinutes(10) td.Triggers.Add(wt) ' Add an action (shorthand) that runs Notepad

    ' NOTE: edit for your own Path to a text file. td.Actions.Add(New ExecAction("notepad.exe", "c:\test.log")) ' Register the task in the root folder ts.RootFolder.RegisterTaskDefinition("Test", td) End Using End Sub End Module



    Regards Les, Livingston, Scotland






    • Edited by leshay Wednesday, September 20, 2017 5:04 PM
    • Marked as answer by Christine25 Thursday, August 15, 2019 10:28 AM
    Wednesday, September 20, 2017 4:36 PM
  • Thanks.

    @ Frank L. Smith

    First off, Sorry about the last time.

    Do you want reasonably good scheduling or thread synchronization?

    not sure what to say? I don't know !

    Please maybe if you can explain me when does an application need "Good scheduling" or "thread synchronization" in order for me to know which one should I go for?

    cause my app stores each task in xml file including its schedule and run the schedule at the specified time.

    So several tasks can be run at same time (that definitely needs Multithreading) if the user planned it.

    Basically, my app is like Windows task scheduler.





    Christine,

    You never replied back but I had a thought early last week that I didn't have time to work on until today.

    It seems to be successful, at least in preliminary testing:

    I used this (excerpt) as the test:

            scheduler = New EventScheduler(Me)
    
            _startingTime = Now
            lbl_StartingTime.Text = _startingTime.ToString
    
            scheduler.AddEvent("Test A", 10, TimeUnits.Seconds)
            scheduler.AddEvent("Test B", 10, TimeUnits.Seconds)
            scheduler.AddEvent("Test C", 3, TimeUnits.Minutes)
            scheduler.AddEvent("Test D", 5, TimeUnits.Minutes)
            scheduler.AddEvent("Test E", #9/23/2017 10:45:00 AM#)

    The results are shown below:

    Think about A and B there: I'm able to raise two separate events at the same time in the same event handler. My original way would raise one event (with two entries) but this one raises different events - in the same event handler. As a note though: A coming in before B is indeterminate because of the inherent slop in the underlying timers.

    It's a combination of your original idea - multiple timers - and a twist on my original idea of using a threading timer (or rather, a wrapper for the threading timer: A System.Timers.Timer). I'm calling the timer a "EventTimer":

        Friend Class EventTimer
            Inherits System.Timers.Timer
    
            Public Property EventName As String
            Public Property TypeOfSchedule As ScheduleType
            Public Property Tag As Object
        End Class

    Once the .Elapsed event is raised, the timer is disposed and the GC will take care of eventually destroying it from memory.

    At any rate, let me know if this appeals to you and if so, we can discuss the specifics and I'll finish it out and upload the whole thing for you. It'll be self-contained inside a single .dll file.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, September 23, 2017 3:59 PM
  • Sorry for the delay !!!

    leshay and everyone who knows.

    How do I call a method/function/sub from "Microsoft.Win32.TaskScheduler" in "td.Actions.Add(New ExecAction("MyMethod()", "c:\test.log"))"

    Sub MyMethod()

    Console.WriteLine("Hello Microsoft !")

    End Sub

    By the way, I want task scheduler to call a method NOT an exe (or an external file) !!!

    and the method which I have to call will then open/load an XML file.

    Is it possible?


    • Edited by Christine25 Friday, October 13, 2017 1:59 PM
    Friday, October 13, 2017 1:46 PM
  • You can read threads at this link VB Forum Search Results for TaskService and read these TaskService.NewTask method, Task Scheduler and Using the Task Scheduler and below links.

    Starting an Executable at a Specific Time

    Task Scheduler 1.0 Examples

    You also need to realize that Task Scheduler can only run at the highest level a user has access to so for example if I was signed onto a system as a normal non-admin user and Task Scheduler tried to run an executable or task that required admin privileges then it could not work for me. Or if it had to access admin privileged files too for example then it would not work for a non-admin user.

    And the console is an .exe (cmd.exe which is registered on systems) and can have commands passed to it via command line type values but I've never tried it with task scheduler.

    Command-Line Reference


    La vida loca

    Friday, October 13, 2017 8:36 PM
  • @ Mr Monkeyboy.

    Thanks for your reply.

    Not sure If you got what I said, I'm NOT looking to start an Executable, but I'm looking to start a method (VB.Net method) at a specified time.

    Basically, I need to load/open XML file at a specified time and get the value which need to be inserted into variables. Not sure if Task Scheduler can accomplish that as I tested Task Scheduler and it appears that Task Scheduler only open the file in Windows (outside VB.Net) but I want the file to be loaded/opened invisibly within VB.Net in order to get the value which I'll use in variables.

    And One told me that Task Scheduler ONLY runs programs, NOT methods. is that true??




    • Edited by Christine25 Saturday, October 14, 2017 10:02 AM
    Saturday, October 14, 2017 9:40 AM
  • Hi

    The only thing I can think of for your needs is this:

    Create a project which has in it's Load event handler, a call to the method you want to run at certain time(s).

    If TaskScheduler runs that programme, then the method would be invoked on start up.

    Sorry, thats all I can think of.


    Regards Les, Livingston, Scotland

    Saturday, October 14, 2017 12:33 PM
  • @ Mr Monkeyboy.

    Thanks for your reply.

    Not sure If you got what I said, I'm NOT looking to start an Executable, but I'm looking to start a method (VB.Net method) at a specified time.

    Basically, I need to load/open XML file at a specified time and get the value which need to be inserted into variables. Not sure if Task Scheduler can accomplish that as I tested Task Scheduler and it appears that Task Scheduler only open the file in Windows (outside VB.Net) but I want the file to be loaded/opened invisibly within VB.Net in order to get the value which I'll use in variables.

    And One told me that Task Scheduler ONLY runs programs, NOT methods. is that true??




    Well as Leshay says you can write a program in VB.Net which can then be executed by Task Scheduler after you properly install the VB.Net program on a system and also add a new task to Task Scheduler, either programmatically or manually to launch the VB.Net program at a specified time.

    Regardless of Task Scheduler it sounds as if you want to open an XML file with a VB.Net program at a specified time in order to gather some variable.

    Others can explain how to read an XML file using VB.Net and there's various posts in this forum you could search for on that.

    However let's say your VB.Net program is not running at the time you desire to get the data from the XML file. So that leaves issues.

    One way to resolve that would be to write a service wrather than a user app so that the service is always running in the background collecting the variables. And have Task Scheduler always launch the service if it is not running on system boot or after that if Task Scheduler detects, I don't know really, if a service set up to run isn't running for some reason. And then you would write a separate application that can get data from the service to display to a user as a service runs in a non-user window and therefore has not display ability without running a user app to access data from the service. Basically the service would always be hidden from users but not an app that can access the service.

    If you just wanted an app to launch at a certain time and be invisible to users and gather data from an XML file and then exit once it has gathered the data or something that is possible also however I don't know how to set up Task Scheduler to do this as I don't have a working PC at this time.

    So you would need to provide the OS you are using as Task Scheduler may not be backwards compatible to various OS's, probably is but you would have to check that, and you would need to explain in greater detail what the idea is.

    AFAIK Task Scheduler could not run VB.Net code but perhaps it could run VB.Script but I've no idea on that and there's scripting forums about using VB.Script.

    And explain what happens after values are retrieved and placed in variables in a hidden program please. I don't see the idea on what to do within the program to provide the variables data to anybody.


    La vida loca

    Wednesday, November 1, 2017 4:54 PM
  • Thanks a lot evey body for your time and precious advice.

    The problem was not the Timer or TimerList, I found the problem further down the code.

    I left a statement / a line of code, that I forgot to delete,

    after browsing down the whole code, I spotted that and deleted it.

    So who does deserve the score???

    Thanks you so so much !!



    • Marked as answer by Christine25 Monday, December 4, 2017 5:41 PM
    • Unmarked as answer by Christine25 Monday, December 4, 2017 5:41 PM
    • Edited by Christine25 Monday, December 4, 2017 5:46 PM
    Monday, December 4, 2017 5:40 PM
  • Hi,

    I recently posted on the below post and they solved my problem as the app is running well,

    but a user called "Cor Ligthert" who proposed me that solution said that I'm not supposed to use that code in production !!!

    Not sure why??  just wanna know if there's another alternative such as library or something else to use instead of his code.

    www.social.msdn.microsoft.com/Forums/vstudio/en-US/1bc71779-4b08-4d85-aaf1-531ed836a008/how-to-run-task-on-specified-timer-from-list-of-structure?forum=vbgeneral


    Christine I write this always when I see that persons use a scheduler with data direct as a form. A Windows Form program can easily be ended by the end user and then all data is gone. 

    There has to be something where the date's are stored even if it is for when the computer gets accidentally down.

    At start up all the known last dates have to be read again and with every change it has to be written.


    Success
    Cor

    Monday, December 4, 2017 7:33 PM
  • Thanks Cor.
    Thursday, December 21, 2017 8:55 AM