Имеется очередь каких-то атомарных операций, в моем случае это порции данных, которые загружаются в БД, также это может быть, например, очередь файлов при копировании. Я хочу вычислять и выводить темп выполнения этих операций, ну, например, чтобы в любой момент я видел, что за последнюю минуту выполнилось 20 операций или, например, 120. Супер точность при этом не нужна - отклонение в 2-5 единиц считаю допустимым. Параллельно в эту же очередь извне могут добавляться еще порции данных, поэтому просто делать отпечаток количества элементов в очереди не получится. Как это реализовать?
Пока набирал вопрос, возникло примерно вот такое решение:
using System;
using System.ComponentModel;
using System.Linq;
using System.Timers;
class Program : INotifyPropertyChanged
{
static void Main(string[] args) => new Program().Run();
int count = 0;
int[] tablet = new int[60];
public int Tempo => tablet.Sum();
public event PropertyChangedEventHandler PropertyChanged;
void Snick()
{
++count;
}
void Cut()
{
int s = DateTime.Now.Second;
tablet[s] = count;
count = 0;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Tempo)));
}
void Run()
{
Timer timer = new Timer(1000);
timer.Elapsed += (s, e) => Cut();
timer.Start();
// ...
while (true)
{
// ...
Snick();
}
timer.Stop();
}
}
Но оно мне пока не до конца нравится, хотя бы тем, что здесь вводится массив и таймер, если я вдруг захочу выводить темп за 1 с - нагрузка от таймера может стать существенной, так же не понятно на какие отрезки разбивать.
Может у кого-то есть уже готовое решение, которое лучше?
А почему так сложно?
Вот такой простой код должен работать:
TimeSpan timeout = TimeSpan.FromMinutes(1);
long OperationsDuringLastMinute { get; private set; }
async void RegisterOperation()
{
OperationsDuringLastMinute++;
await Task.Delay(timeout);
OperationsDuringLastMinute--;
}
В конце каждой операции вызывайте RegisterOperation
(в главном потоке).
Если у вас не UI-контекст, то, как подсказывает @Raider в комментариях, вам понадобятся атомарные операции.
long operationsDuringLastMinute;
long OperationsDuringLastMinute
{
get { return Interlocked.Read(ref operationsDuringLastMinute); }
}
async void RegisterOperation()
{
Interlocked.Increment(ref operationsDuringLastMinute);
await Task.Delay(timeout);
Interlocked.Decrement(ref operationsDuringLastMinute);
}
Если нужно отслеживать выполнение какой-либо длительной операции независимо от неё самой, в любом случае понадобится 2 потока, и какая-то общая область памяти, куда будет записываться общий прогресс.
Таймер здесь не нужен: во-первых, для него берется еще один (не вдаваясь в подробности) ненужный поток из thread pool, во-вторых, его точность уж совсем хромает, и не для того он был создан.
Для замеров точных меток времени в .NET есть класс Stopwatch
, но так как ваша задача - посчитать количество операций за последнюю минуту, то переменной с предыдущим замером в сочетании с Thread.Sleep
будет достаточно. При желании, Stopwatch
и Thread.Sleep
можно скомбинировать для получения более точного результата.
Для наглядности, я использовал квантование по секунде, но интервал легко меняется параметром метода:
public static class Program
{
private static readonly ConcurrentQueue<string> Results = new ConcurrentQueue<string>();
static void Main(string[] args)
{
Task work = Task.Run(new Action(DoWork));
MeasureRate(work, Results);
Console.WriteLine("Completed!");
}
private static void MeasureRate<T>(IAsyncResult work, IReadOnlyCollection<T> results, int timing = 1000 /* 1 second */)
{
int previousCount = 0;
do
{
Console.WriteLine("Current rate: {0} entries per second", results.Count - previousCount);
previousCount = results.Count;
Thread.Sleep(timing);
} while (!work.IsCompleted);
}
private static void DoWork()
{
var randomizer = new Random();
for (int i = 0; i < 100000; i++)
{
Thread.Sleep(randomizer.Next(100));
Results.Enqueue("Result " + i);
}
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Внутри модели есть живой список устройств, у каждого устройства есть свои поляКак оповещать список в VM, чтоб тот обновил View?
мне надо сверстать такую таблицу: Проблема в том, что я не знаю как сделать чтобы последний ряд зависил от предыдующего: чтобы к двойке принадлежали...
Что за рамка и как его удалить (или заменить именной цвет на другое посредством JS), при указании свойства width: 100% для изображения появляется...