-1

how do I have something constantly running as a background process, without affecting any other running code, for example the asynchronous function could have a 5 second wait, but that would not affect anything else.

  • Try to use [`Task Class`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task?view=net-5.0). – 大陸北方網友 Jan 11 '21 at 03:14
  • 1
    The very definition of "asynchronous" means you can't count on the increment happening right when you need it to. – Joel Coehoorn Jan 11 '21 at 03:15
  • Perhaps you would want to have a separate thread running for this purpose? – Dash Jan 11 '21 at 03:21
  • "*but that would not affect anything else*" - What exactly does this mean? Have you tried a the Timer class? Also this question is only slightly better than your last https://stackoverflow.com/questions/65660300/how-would-i-make-a-variable-passively-gain-1-say-every-1-minute-without-running – TheGeneral Jan 11 '21 at 03:35
  • Also have you seen this question https://stackoverflow.com/questions/12535722/what-is-the-best-way-to-implement-a-timer – TheGeneral Jan 11 '21 at 03:37
  • "but that would not affect anything else" - this means that it would run on its own, without having that pause any other processes. i am also new to stack overflow.@00110001 – grumblermannice Jan 11 '21 at 04:07

1 Answers1

1

The most easy would be System.Timers.Timer

TimeSpan interval = TimeSpan.FromSeconds(5);
var timer = new System.Timers.Timer()
{
    Interval = interval.TotalMillisends,
    AutoReset = true,
};
timer.Elapsed += TimerTick;
timer.Enabled = true;


void TimerTick(object sender, ElapsedEventHandler e)
{
     ProcessTimerTick(e.SignalTime);
}

Start / Stop the timer is done using property Enabled. Don't forget to Dispose the timer if your form is disposed.

Although this will free up your UI, be aware that procedure TimerTick is run by the UI thread. So whenever TimerTick is processing the TimerTick, the UI freezes. Make sure that this doesn't take too long.

Another method would be to start a Task that call ProcessTimerTick every 5 seconds. To be able to stop the timer you need a CancellationTokenSource.

private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task timerTask = Task.CompletedTask;

async Task TimerProcedure(TimeSpan delayTime, CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        await Task.Delay(delayTime, cancellationToken);
        await ProcessTimerTick(DateTime.utcNow, cancellationToken);
    }
}

Start the timer task:

book IsTaskRunning => !this.timerTask?.IsTaskCompleted ?? false;

async Task StartTimerTaskAsync(TimeSpan delayTime)
{
    if (this.IsTaskRunning)
    {
        // TODO: what to do if already a Task is running? Stop the old TimerTask?
        await CancelTimerTaskAsync();
    }
    this.cancellationTokenSource.Dispose();
    this.cancellationTokenSource = new CancellationTokenSource();
    this.timerTask.Dispose();
    this.timerTask = Task.Run( () => TimerProcedure(delayTime, cancellationTokenSource.Token);
}

To cancel the task and wait until it is completed:

async Task CancelTimeTaskAsync()
{
    this.CancellationTokenSource.Cancel();
    await this.TimerTask;
}

Don't forget to Cancel the task when your form is closing. Don't forget to Dispose the Task and the CancellationTokenSource when you form is being Closed, or at its latest when the form is Disposed.

You see: using async await needs a lot of extra code. Besides the timer ticks are not accurate. If the TimerProcedure takes 100 msec, then the total time will be 5.1 sec.

The timer procedure won't run on the UI thread. This might be an advantage, except if the timer procedure needs to update UI elements.

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116