简体   繁体   English

如何在C#中使受控无限循环异步?

[英]How to make a controlled infinite loop async in c#?

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. 因为while循环仍然运行。

How can I set it so that while its paused, nothing executes? 如何设置它,使其在暂停时不执行任何操作?

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). 很难回答:如果将“ pause”定义为: the object state remains valid while the loop doesn't use any resources则必须停止并重新启动它(循环)。

All other timers, including Thread.Sleep , Task.Delay s etc. will put your thread in idle/suspended mode. 所有其他计时器,包括Thread.SleepTask.Delay等等,都将使您的线程处于空闲/暂停模式。

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 Thread.sleep代码

More about sleep 有关睡眠的更多信息

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". 您可以使用System.Threading.Timer并在不使用它时进行处理,并在准备“恢复”时重新创建它。 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
}

If you are really adverse to timers and want it to look like a while loop, then you can use TaskCompletionSource<T> : 如果您确实对计时器不利,并且希望它看起来像while循环,那么可以使用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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM