In my program there is a function that should be executed only at a certain time (dd / mm / yyyy). The user enters a date, and only at that time the function is executed. how to implement a timer?

    1 answer 1

    One of a million ways. For example:

    async Task ExecuteAfter(DateTime when, Action function) { DateTime now = DateTime.Now; if (when > now) await Task.Delay(when - now); function(); } 

    Other method:

     DateTime now = DateTime.Now; if (when <= now) { function(); } else { var milliseconds = (when - now).TotalMilliseconds; var timer = new System.Timers.Timer(milliseconds) { AutoReset = false }; timer.Elapsed += (o, args) => { function(); timer.Stop(); timer.Dispose(); }; // если вы пишете на WinForms, можете указать ещё // timer.SynchronizingObject = <any control> // чтобы вызов произошёл в UI-потоке timer.Start(); } 

    One more:

     DateTime now = DateTime.Now; if (when <= now) { function(); } else { System.Threading.Timer timer = null; timer = new System.Threading.Timer( o => { function(); timer.Dispose(); }, null, when - now, TimeSpan.Zero); } 

    Another approach is to use synchronization primitives and wait for an event with a timeout that will never come. For example, using the semaphore:

     DateTime now = DateTime.Now; if (when > now) using (var sema = new SemaphoreSlim(0)) sema.Wait(when - now); function(); 

    (Not recommended, blocks the current stream!)


    Another method, the use of threads + Sleep . Not recommended, since it blocks the flow, and this is an unnecessary waste of resources. The worst method is blocking the current thread:

     DateTime now = DateTime.Now; if (when > now) Thread.Sleep(when - now); function(); 

    Slightly better idea with unloading in a separate thread:

     new Thread(() => { DateTime now = DateTime.Now; if (when > now) Thread.Sleep(when - now); function(); }) { IsBackground = true }.Start(); 

    A little better is to use thread pool (but still bad):

     ThreadPool.QueueUserWorkItem(o => { DateTime now = DateTime.Now; if (when > now) Thread.Sleep(when - now); function(); }); 
    • Be careful with falling asleep for more than 10 days. If you try to fall asleep for such a super-long period of time, the flow may never wake up. Timers may also not work. I caught such a bug on XP SP3. - Pavel Mayorov
    • @PavelMayorov: Well, this is a bug. Just wanted to add a blocking flow method. The current three methods do not seem to get into this problem. - VladD
    • Superlong timers will also not start if there are no other timers in the program. - Pavel Mayorov
    • @PavelMayorov: I didn’t quite understand what you mean, show sample code? - VladD
    • await Task.Delay(TimeSpan.FromDays(20.0)) all, if no code uses timers, this timer will never work again. - Pavel Mayorov