Casper-SC
@Casper-SC
Программист (.NET)

Получить среднее значение в секунду. Как это сделать более правильно?

Здравствуйте. Мне нужно рассчитать среднее значение полученных данных в секунду.
Например, есть класс:

class StateMonitor
    {
        private long _quantityOfValues;
        private long _quantityOfCalls;

        private readonly object _quantityOfValuesSync = new object();
        private readonly object _frequencySync = new object();

        public void Increment()
        {
            lock (_quantityOfValuesSync)
            {
                ++_quantityOfValues;
            }
        }

        public int Frequency
        {
            get
            {
                long quantityOfValues;
                lock (_quantityOfValuesSync)
                {
                    quantityOfValues = _quantityOfValues;
                }

                lock (_frequencySync)
                {
                    double result = (double)quantityOfValues / ++_quantityOfCalls;
                    result = Math.Round(result, MidpointRounding.AwayFromZero);
                    return (int)result;
                }
            }
        }
    }


Чтобы он правильно считал частоту вызова метода Increment в секунду нужно вызывать свойство Frequency 1 раз в секунду. Что нельзя назвать удобным и надёжным. Наверняка есть формула для такого подсчёта. Догадываюсь, что нужно будет сохранять время последнего вызова свойства Frequency, чтобы правильно считать. Чёт никак не допетрю, как же правильно считать?

Вот код для теста класса выше:
using System;
using System.Threading;
using System.Threading.Tasks;

namespace FrequencyReceivingTest2
{
    internal class Program
    {
        #region Entry point

        private static Program _program;

        private static void Main(string[] args)
        {
            _program = new Program();
            _program.Run(args);
        }

        #endregion

        private void Run(string[] args)
        {
            var monitor = new StateMonitor();
            int counter = 0;

            Task[] tasks =
            {
                new Task(() =>
                {
                    while (counter++ < 20)
                    {
                        int ms = 0;
                        while (ms < 1000)
                        {
                            const int WaitMs = 200;
                            monitor.Increment();
                            Thread.Sleep(WaitMs);
                            ms += WaitMs;
                        }
                    }
                }),

                new Task(() =>
                {
                    while (counter < 20)
                    {
                        Console.WriteLine("Частота обновления: {0}/сек. ", monitor.Frequency);
                        Thread.Sleep(1000);
                    }
                }),
            };

            Array.ForEach(tasks, task => task.Start());

            Task.WaitAll(tasks);
            Console.WriteLine("Конец.");
            Console.ReadKey();
        }
    }
}
  • Вопрос задан
  • 398 просмотров
Пригласить эксперта
Ответы на вопрос 2
С мобилы , неудобно посмотреть. Есть два варианта подсчёта частоты.
1 за последнюю секунду считать частоту, держите очередь, удаляете что дольше 1 сек живет,добавляете новые тики, пересчитывает частоту, это длина очереди. 2 вариант сложнее. Тоже самое, но на разных промежутках времени(менее 1 сек в пересчете для 1 сек), если это необходимо.
Например 2 события в 200 мс, это 10 событий в 1 сек. Все абстрактно описал.
Ответ написан
Комментировать
@res2001
Developer, ex-admin
Сохраняете timestamp первого и последнего вызова Increment. Количество вызовов в секунду легко расчитываете по требованию: quantityOfValues/(tend-tbegin). (tend-tbegin), конечно, нужно преобразовать в секунды.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы