首页 新闻 会员 周边 捐助

请教:c#数值比较一个延时判定的程序思路

0
悬赏园豆:30 [已解决问题] 解决于 2020-01-08 11:17

请教各位大侠,目前有如下需求不知如何实现:
数值A和数值B不停的比较,数值A为一个定值,数值B是通过远端采集过来的一个数值,当数值B在一定时间内与数值A不相等时,触发一个bool变量为1,
实际应用中,需要涉及到几十个这样的比较,考虑使用类做数值比较的延时判断,但是发现单次调用类导致数值B无法实时跟随远端采集过来的数据刷新(进入类后,使用调用类瞬时的数值B),这样类中的延时判断也就没有实际意义了,如果循环调用类,那延时判定时间如何累加又不知道如何实现了,
请各位大侠给个思路,新手上路,谢谢!

rossi努力努力的主页 rossi努力努力 | 初学一级 | 园豆:8
提问于:2019-12-26 09:32
< >
分享
最佳答案
0

这种问题使用 Rx.Net 可以很方便的解决:

using System;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace RxDemo
{
    class Program
    {
        private static readonly Random Rnd = new Random(42);
        private const int A = 1;

        static void Main(string[] args)
        {
            var period = TimeSpan.FromSeconds(3);
            var result = ObserveResult(period, samplePeriod: TimeSpan.FromSeconds(1));
            using var sub = result.Subscribe(
                x =>
                {
                    if (x)
                    {
                        Console.WriteLine($"[{DateTime.Now:hh:mm:ss}] all B != A in " + period);
                    }
                    else
                    {
                        Console.WriteLine($"[{DateTime.Now:hh:mm:ss}] not all B != A in " + period);
                    }
                });
            Console.ReadKey();
        }

        static Task<int> FetchValueBAsync()
        {
            return Task.FromResult(Rnd.Next(0, 3));
        }

        static IObservable<int> ObserveB(TimeSpan samplePeriod)
        {
            return Observable.Timer(dueTime: TimeSpan.Zero, period: samplePeriod)
                .SelectMany(_ => FetchValueBAsync());
        }

        static IObservable<bool> ObserveResult(TimeSpan period, TimeSpan samplePeriod)
        {
            return ObserveB(samplePeriod)
                .Do(b => Console.WriteLine($"[{DateTime.Now:hh:mm:ss}] Fetched B: {b}")) // 记录一下 B 的值以及采样时间
                .Buffer(period) // 把一段时间内的 B 的值打包成一个数组
                .Select(x => x.All(b => b != A)); // 当每个数组中的所有结果为 true 时,表示这段时间所有的 B != A
        }
    }
}

样例输出:

[10:58:31] Fetched B: 2
[10:58:32] Fetched B: 0
[10:58:33] Fetched B: 0
[10:58:34] all B != A in 00:00:03
[10:58:34] Fetched B: 1
[10:58:35] Fetched B: 0
[10:58:36] Fetched B: 0
[10:58:37] not all B != A in 00:00:03

B 的值是远程采集的,不管是推送给你还是你主动去拉取,肯定会有一个采样频率,这个行为我用 ObserveB(TimeSpan samplePeriod) 来模拟。这个函数返回的是一个 IObservable<int>,代表 B 的值随时间改变的序列。在你实际的代码中你需要自己实现这个函数。

ObserveResult(TimeSpan period, TimeSpan samplePeriod) 才是实现 “当数值B在一定时间内与数值A不相等时,触发一个bool变量为1” 的要点。这里的核心是 Buffer 操作符,用来将一段时间内的数据收集到一个数组中。

收获园豆:10
不如隐茶去 | 小虾三级 |园豆:559 | 2019-12-26 11:15

您的方式 Rx.Net,我还是第一次接触,我的好好消化消化,谢谢大侠的指点

rossi努力努力 | 园豆:8 (初学一级) | 2019-12-26 21:23
其他回答(3)
0

//定义一个时间,用于存储上次A=B的时间
DateTime lastEqualTime;

    //在B更新值后或者你自己以一定时间频率去触发
    void AfterUpdateBOrSomeTime()
    {
        if (A = B)
        {
            lastEqualTime = DateTime.Now;
        }
        else
        {
            ///当数值B在一定时间内与数值A不相等时
            if (lastEqualTime - DateTime.Now > someFixedTimeSpan)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
收获园豆:10
猝不及防 | 园豆:2878 (老鸟四级) | 2019-12-26 09:44

博问支持 markdown 代码高亮

支持(0) 反对(0) dudu | 园豆:29618 (高人七级) | 2019-12-26 09:58

大侠,您这个我么看懂,能在详细说下思路吗?

支持(0) 反对(0) rossi努力努力 | 园豆:8 (初学一级) | 2019-12-26 10:12

@dudu: 好的dudu大佬

支持(0) 反对(0) 猝不及防 | 园豆:2878 (老鸟四级) | 2019-12-26 10:24

@rossi1984: 修改了

支持(0) 反对(0) 猝不及防 | 园豆:2878 (老鸟四级) | 2019-12-26 10:25

@dudu: 大佬能留步指点一下吗?

支持(0) 反对(0) rossi努力努力 | 园豆:8 (初学一级) | 2019-12-26 21:25

@rossi1984: 建议先提供一下你目前的实现代码

支持(0) 反对(0) dudu | 园豆:29618 (高人七级) | 2019-12-26 22:20

@dudu: 回大佬
button_click事件触发标志位
timer_Tick //定时器循环执行
{

if(button_click_标志位)
{

  if(A==B)
     {
      相等标志位=1;
      不相等累计值=0;
     }
   else
     {
     不相等累计值 + =1;//累计,每次循环+1
     }
  
  if(不相等累计值 > 设定值 )
    {
     故障标志位=1;
     button_click_标志位=0;
     break;
    }
}

}
如上是我最初想到的笨方法,考虑到应用会有很多,一个一个这样写,难以想象,楼下几位大侠的队列思路,也挺好,但是我没想通如何兼顾类的通用,以及保证数据的刷新,如何实现?

支持(0) 反对(0) rossi努力努力 | 园豆:8 (初学一级) | 2019-12-27 11:04

@dudu: 结贴前,大佬能不能给点指点,谢谢

支持(0) 反对(0) rossi努力努力 | 园豆:8 (初学一级) | 2020-01-06 09:09
0

条件:
A是一个定值,
B是一个不停取来的新数值,
一段时间内A!=B bool 标志=1
解决方法:
定义一个容器, DataTable 或 数组 或 队列 或 链表 或 map
收到一个B,就按队列放到容易器里面
每隔一段时间就在这个容器里判断这个值是否相同, 判断后清空已经处理过的接收数据

收获园豆:5
风浪 | 园豆:2996 (老鸟四级) | 2019-12-26 10:33

大侠,您把问题归纳的非常透彻,但是您说的方法,我想了许久,没有想出使用类的方式实现的办法,由于我这里需要这种比较的变量非常多,您能在费心讲讲吗?

支持(0) 反对(0) rossi努力努力 | 园豆:8 (初学一级) | 2019-12-26 21:22
0

这种有传输和运行,不能排除时间会有延迟,但是可以尽优化。
你的要求是判断不等就改状态,你考虑从多个端口过来,改一个状态? 如果是这样,可以考虑并行计算,只要不等就改状态,剩下没算完的也以不比了。
如果是多个端口过来是多个状态修改,也有并行计算有关,但是不上面一种情况,这个只是都需要计算完。

收获园豆:5
gw2010 | 园豆:1487 (小虾三级) | 2019-12-26 11:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册