0

I found this

Run async method regularly with specified interval

which does half of what I want, but at the same time I want to be able to stop the loop whenever I want and then resume it as well. However while it's stopped, I don't want the infinite loop to keep running where the body gets skipped through a flag.

Basically I don't want this

while (true) {
    if (!paused) {
        // run work
    }
    // task delay
}

because then the while loop still runs.

How can I set it so that while its paused, nothing executes?

omega
  • 40,311
  • 81
  • 251
  • 474
  • 1
    Use [Timers](https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer) to off-load logic. – JohnyL Aug 09 '18 at 18:40
  • does that requires user input (pause/resume) or is it timer based? is it windows application? – Vinit Aug 09 '18 at 18:42
  • You could use `System.Threading.Timer` and dispose of it while it is not in use and re-create it when you are ready to "resume". These timers are light weight, that would be the easiest option IMO. – Igor Aug 09 '18 at 18:51
  • You should describe what you're actually trying to do - as it is, your question is very abstract and hard to answer. It almost seems like you'd need to use some sort of workflow engine - you can easily stop any processing between steps (but not a particular step). I assume your infinite loop cannot be stopped at an arbitrary point, only at certain checkpoints (and then it'd have to pick up from there). – xxbbcc Aug 09 '18 at 19:15

3 Answers3

0

How can I set it so that while its paused, nothing executes?

That's hard to answer: if you define "pause" as: the object state remains valid while the loop doesn't use any resources then you'll have to stop and restart it (the loop).

All other timers, including Thread.Sleep, Task.Delays etc. will put your thread in idle/suspended mode.

If that's not sufficient for your needs, you'll need to actually stop the "infinite" loop.

It will free up thread related resources as well.

More info about sleep:

Thread.Sleep

More about sleep

Stefan
  • 17,448
  • 11
  • 60
  • 79
0

You could use System.Threading.Timer and dispose of it while it is not in use and re-create it when you are ready to "resume". These timers are light weight so creating and destroying them on demand is not a problem.

private System.Threading.Timer _timer;

public void StartResumeTimer()
{
  if(_timer == null)
    _timer = new System.Threading.Timer(async (e) => await DoWorkAsync(e), null, 0, 5000);
}

public void StopPauseTimer()
{
  _timer?.Dispose();
  _timer = null;
}

public async Task DoWorkAsync(object state)
{
   await Task.Delay(500); // do some work here, Task.Delay is just something to make the code compile
}
Igor
  • 60,821
  • 10
  • 100
  • 175
0

If you are really adverse to timers and want it to look like a while loop, then you can use TaskCompletionSource<T>:

private TaskCompletionSource<bool> _paused = null;

public async Task DoWork()
{
    while (true)
    {
        if (_paused != null)
        {
            await _paused.Task;
            _paused = null;
        }
        //run work
        await Task.Delay(100);
    }
}

public void Pause()
{
    _paused = _paused ?? new TaskCompletionSource<bool>();
}

public void UnPause()
{
    _paused?.SetResult(true);
}
Dave M
  • 2,863
  • 1
  • 22
  • 17