【问题标题】:Simultaneously detect change in value within a 4 second period在 4 秒内同时检测值的变化
【发布时间】:2021-08-10 20:53:00
【问题描述】:

我有一个事件,它大约每 100 毫秒从 api 值返回一个不同的整数。

我想在任何给定的 4 秒内事件中整数的差为 20 或更大时执行一些代码。

这里是每 100 毫秒返回 int 值的当前事件

private void OnMarketUpdate(object sender, UpdateArgs<L1LsPriceData> e)
{
    var data = e.UpdateData;
    int = data.intValue;
}

由于重叠,我无法创建一个计时器来每 4 秒检查一次,例如。计时器经过 2 秒后,到下一个计时器经过 2 秒后,可能会有 20 或更多的变化,但不会被检测到,因为它在 2 个不同的调用中。

如果有办法至少每秒运行 4 秒计时器以检测上面更新事件中的变化,那已经足够了,但不知道该怎么做。

任何帮助将不胜感激:)

【问题讨论】:

  • 你应该查看StopWatch类:docs.microsoft.com/en-us/dotnet/api/…
  • 您对 Rx (Reactive Extensions) 解决方案感兴趣吗?或者您不想在项目中添加依赖项?
  • 添加一个 lastTrue 日期时间变量。在 onmarketupdated 中,将其设置为您的条件为真时的当前时间。然后在计时器滴答声中,您可以每秒检查一次,看看 lastTrue 是否在 4 秒内。我不清楚您是否还需要设置 lastTrue 以在您采取行动时设置为 mindate 或其他类似的设置,但这似乎很可能。
  • 使用 utcnow 作为当前时间以避免任何系统时间或夏令时异常。

标签: c# .net wpf multithreading timer


【解决方案1】:

将当前日期/时间与列表中的值一起存储并更新列表以包含最后 4 秒的数据。

private List<(DateTime time, int value)> _lastValues = new();

private void OnMarketUpdate(object sender, UpdateArgs<L1LsPriceData> e)
{
    var now = DateTime.UtcNow;

    // Keep only values of the last 4 seconds
    _lastValues = _lastValues
        .Where(x => (now - x.time) <= TimeSpan.FromSeconds(4))
        .ToList();

    var data = e.UpdateData;
    int value = data.intValue;
    _lastValues.Add((now, value)); // Add current value

    int min = _lastValues.Min(x => x.value);
    int max = _lastValues.Max(x => x.value);
    if (max - min >= 20) {
        // execute some code
    }
}

我正在使用 C# 7.0 及更高版本中提供的Tuple types。您也可以改用KeyValuePair&lt;K,V&gt;

我也用过C# 9.0: Target-typed New Expressions

【讨论】:

  • 如果系统调整时间,该解决方案将如何表现?例如,由于daylight saving time,时间从 23:59:59 调整到 23:00:00。
  • 不知道。这种棘手的日期时间边缘案例是 Jon Skeet 的 Noda Time 的专长。但是将代码更改为使用UtcNow。但由于使用了内部的Ticks,这可能是现在相关的。
  • 您可以考虑使用Environment.TickCount,而不是DateTime.UtcNow,AFAIK 不受系统时钟调整的影响。或使用Stopwatch
猜你喜欢
  • 1970-01-01
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 2011-11-24
  • 2018-01-03
  • 2016-10-04
相关资源
最近更新 更多