0

I was initially using ObservableClass to store my CPU Usage information every second and move this information to a chart which was working but kept adding on to memory.

Got some advice and moved to opt for a Queue class to be able to remove the information after a certain period has passed. But unlike an observable class, I can't store 2 arguments.

Should I use both queue and observable class or queue class is enough for my issue.

Initial codes using Observable class

class CPUClass{ 
     ObservableCollection<KeyValuePair<double, double>> cpuChartList = new ObservableCollection<KeyValuePair<double, double>>();

    //this method is fired off every second
    private void timerChange(){
        counter += 1; 
        //cpuCurrent is the current cpu usage value every second
        cpuChartList.Add(new KeyValuePair<double, double>(counter, cpuCurrent));
    }
}

//On the MainWindow
cpulineChart.DataContext = CPUClass.cpuChartList;

Trying with Queue Class

class CPUClass{
    Queue queueCPU = new Queue();

    //to hold past 30 seconds cpu usage information at any point
    private void timerChange(){
        counter += 1;
        if (queueCPU.Count > 30)
            {
                queueCPU.Dequeue();
                counter -= 1;
            }
        queueCPU.Enqueue(cpuCurrent);//
    }
}

//On the MainWindow
cpulineChart.DataContext = CPUClass.queueCPU;

As you can see when using Queue Class, I am not able to include my counter to keep track of seconds on the chart. This is new to me thus could have messed up the whole concept. Also pondering if the way I am adding and removing the counter for the Queue Class way is messy. Please advice. Thank you.

kar
  • 4,791
  • 12
  • 49
  • 74
  • Check this SO post for implementing a fixed length queue - http://stackoverflow.com/questions/5852863/fixed-size-queue-which-automatically-dequeues-old-values-upon-new-enques – siddharth Mar 01 '14 at 11:39
  • Tnks for reply. I am looking for a way to implement the queue such that it take in 2 arguments similar to the ObservableCollection. – kar Mar 01 '14 at 12:14

1 Answers1

1

I have not used a queue here, but I think this is what you want to do. You want to update your observable collection every second and remove the oldest item stored in it. Based on this, I have provided the code below.

Hope this helps.

public class CPUClass
{
    public ObservableCollection<KeyValuePair<double, double>> cpuChartList = new ObservableCollection<KeyValuePair<double, double>>();
    private object _lock = new object();
    private int _counter;
    private int _Limit = 30; //max 30 secs of data

    Timer _timer;

    public CPUClass()
    {
        _timer = new Timer(1000);
        _timer.Elapsed += _timer_Elapsed;
        _timer.Enabled = true;

        _counter = 0;

    }

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        App.Current.Dispatcher.Invoke(() => UpdateCollection());
    }

    void UpdateCollection()
    {
        lock (_lock)
        {
            _counter += 1;

            //Get the CpuUsage
            var cpuCurrent = GetCpuUsage();

            //Remove the oldest item
            if (cpuChartList.Count >= _Limit)
                cpuChartList.RemoveAt(0);
            cpuChartList.Add(new KeyValuePair<double, double>(_counter, cpuCurrent));
        }
    }


}
siddharth
  • 660
  • 2
  • 6
  • 18
  • This works. Just want to clarify something. When you use .RemoveAt method, does that clear that information from memory or still remains stored in the background? – kar Mar 01 '14 at 16:46
  • The object will persist in the memory after being removed from the collection, until its marked for disposing off by the garbage collector. You can force a garbage collection using `GC.Collect` but its generally not recommended. You can read about it here - http://stackoverflow.com/questions/1149197/gc-collect. Also if you want to force a GC.Collect, you can probably put a condition to do so after say every 60 secs or so. `if(_counter % 60 == 0) { GC.Collect; }` – siddharth Mar 01 '14 at 17:54