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

2020-01-08 10:40发布

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

标签:
4条回答
成全新的幸福
2楼-- · 2020-01-08 10:51

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

查看更多
混吃等死
3楼-- · 2020-01-08 10:51

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

查看更多
Deceive 欺骗
4楼-- · 2020-01-08 10:58

//定义一个时间,用于存储上次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;
            }
        }
    }
查看更多
一纸荒年 Trace。
5楼-- · 2020-01-08 11:11

这种问题使用 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 操作符,用来将一段时间内的数据收集到一个数组中。

查看更多
登录 后发表回答