How to delay a C# Action like QTimer::singleShot?

  • A+
Category:Languages

Qt has a neat functionality to do timed action with Lambda.

An action can be done after a delay with a single line of code:

    QTimer::singleShot(10, [=](){         // do some stuff     }); 

Although I haven't found equivalent in C#.


The closest I got was

Timer timer = new Timer(); timer.Interval = 10; timer.Elapsed += (tsender, args) => {    // do some stuff    timer.Stop(); }; timer.Start(); 

But it's far from (visually) clean.

Is there a better way to achieve this ?

The use case is sending data on a serial line to some hardware, upon a button click or action, it is often required to send a command, and a packet a few ms later.


Solution with a helper function:

    public void DelayTask(int timeMs, Action lambda)     {         System.Timers.Timer timer = new System.Timers.Timer();         timer.Interval = timeMs;         timer.Elapsed += (tsender, args) => { lambda.Invoke(); };         timer.AutoReset = false;         timer.Start();     } 

Called by

DelayTask(10, () => /* doSomeStuff...*/ ); 

 


The closest thing I would think of would be something like an helper function like you suggested:

public static class DelayedAction {     public static Task RunAsync(TimeSpan delay, Action action)     {        return Task.Delay(delay).ContinueWith(t => action(), TaskScheduler.FromCurrentSynchronizationContext());     } } 

The usage of the class would be close to what you know with Qt:

await DelayedAction.RunAsync(TimeSpan.FromSeconds(10), () => /* do stuff */); 

Update

As mentioned in an existing SO question, ContinueWith does not keep the synchronization context by default.

In the current question, the lambda is updating some UI control and, as such, must be run on the UI thread.

To do so, the scheduler must specify the synchronization context when calling the method ContinueWith (TaskScheduler.FromCurrentSynchronizationContext()) to make sure such update is possible.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: