异步睡眠循环

福恩

因此,对于我的项目,我需要每100毫秒从一块硬件中获取值。提取需要x毫秒的时间。因此,我正在寻找但找不到的是一种确保for / while始终花费100毫秒(或更长时间)的方法。

因此在伪代码中:

for (int i = 0; i < 100; i++) // Take measurements for 10 seconds
{
    // Call some async method that sleeps for 100 ms
    this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Temperature)); // Takes 15 ms
    this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Pressure)); // Takes 30 ms
    // await async method to finish
}

我已经尝试了一些异步等待的方法,但是我似乎无法理解。谁能帮助我找到一种可靠的方法来获取100秒间隔的10秒测量结果?

编辑:我知道,因为我在Windows上运行C#,所以计时实际上不是一个有效的选择。但这对我的问题并不重要。我的问题是,如何确保for循环至少要花100毫秒(!!!),同时尽可能接近100毫秒。

拉瑟诉卡尔森

一种方法是创建一个秒表,并在完成每个操作后等待其到达下一个里程碑。

这种方式的好处是:

  • 您将把循环的开销添加到混合中,调整延迟以补偿
  • 这样,它应该几乎没有“漂流”(根据操作发生的时间,操作将逐渐“后移”)

有点像这样:

var sw = Stopwatch.StartNew();
long next = 100;
while (sw.ElapsedMilliseconds < 10000)
{
    // do your operation here
    long left = next - sw.ElapsedMilliseconds;
    if (left > 0)
        await Task.Delay((int)left);
    next += 100;
}

由于事情的准确性,您的操作大约每100毫秒进行一次,但它们不应漂移。

如果可以在这10秒钟的时间内绑定线程,则可以通过以下方式切换延迟部分Thread.Sleep

if (left > 0)
    Thread.Sleep((int)left);

它将使您的操作更接近100毫秒标记,但由于Thread.Sleep也会产生一些开销因此开销可能仍然很小

如果您对“刻录CPU”没问题,可以改为执行以下操作:

var sw = Stopwatch.StartNew();
var next = 100;
while (sw.ElapsedMilliseconds < 10000)
{
    // do your operation here
    
    while (sw.ElapsedMilliseconds < next) ;
    next += 100;
}

这将运行您的操作更接近实际的100毫秒标记,因为Task.DelayThread.Sleep将有开销往往会比你的原意只是稍微更长的延迟。但是,它将在那10秒钟的时间内占用CPU内核。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章