public void updateGraph(int[] data)
        {
            lock (_syncRoot) {
                Parallel.For(0, dataNumber, j => {
                    try {
                        actualData[i][j] = data[j];
                    } catch (IndexOutOfRangeException e) {
                    }
                });

                //suspending updates for full update when all data are set
                using (dataSeries.SuspendUpdates()) {
                    dataSeries.CopyFrom(actualData);
                }

                if (i < (dataNumber - 1))
                {
                    i++;
                }
                else
                {
                    int[][] tmp = new int[dataNumber][];
                    Array.Copy(actualData, 1, tmp, 0, actualData.Length - 1);
                    actualData = tmp;
                    actualData[dataNumber - 1] = new int[dataNumber];
                }
            };
        }
        private void OnStart()
        {
            if (!IsLoaded)
            {
                return;
            }

            string whatData = (string)DataCombo.SelectedItem;
            int    w = 0, h = 0;

            if (whatData == "3D Sinc 10 x 10")
            {
                w = h = 10;
            }
            if (whatData == "3D Sinc 50 x 50")
            {
                w = h = 50;
            }
            if (whatData == "3D Sinc 100 x 100")
            {
                w = h = 100;
            }
            if (whatData == "3D Sinc 500 x 500")
            {
                w = h = 500;
            }
            if (whatData == "3D Sinc 1k x 1k")
            {
                w = h = 1000;
            }

            lock (_syncRoot)
            {
                OnStop();
            }

            var dataSeries = new UniformGridDataSeries3D <double>(w, h)
            {
                StartX     = 0,
                StartZ     = 0,
                StepX      = 10 / (w - 1d),
                StepZ      = 10 / (h - 1d),
                SeriesName = "Realtime Surface Mesh",
            };

            var frontBuffer = dataSeries.InternalArray;
            var backBuffer  = new GridData <double>(w, h).InternalArray;

            int frames = 0;

            _timer          = new Timer();
            _timer.Interval = 20;
            _timer.Elapsed += (s, arg) =>
            {
                lock (_syncRoot)
                {
                    double wc = w * 0.5, hc = h * 0.5;
                    double freq = Math.Sin(frames++ *0.1) * 0.1 + 0.1;

                    // Each set of dataSeries[i,j] schedules a redraw when the next Render event fires. Therefore, we suspend updates so that we can update the chart once
                    // Data generation (Sin, Sqrt below) is expensive. We parallelize it by using Parallel.For for the outer loop
                    //  Equivalent of "for (int j = 0; j < h; j++)"
                    // This will result in more CPU usage, but we wish to demo the performance of the actual rendering, not the slowness of generating test data! :)
                    Parallel.For(0, h, i =>
                    {
                        var buf = frontBuffer;
                        for (int j = 0; j < w; j++)
                        {
                            // 3D Sinc function from http://www.mathworks.com/matlabcentral/cody/problems/1305-creation-of-2d-sinc-surface
                            // sin(pi*R*freq)/(pi*R*freq)
                            // R is distance from centre

                            double radius = Math.Sqrt((wc - i) * (wc - i) + (hc - j) * (hc - j));
                            var d         = Math.PI * radius * freq;
                            var value     = Math.Sin(d) / d;
                            buf[i][j]     = double.IsNaN(value) ? 1.0 : value;
                        }
                    });

                    using (dataSeries.SuspendUpdates())
                    {
                        dataSeries.CopyFrom(frontBuffer);
                        var temp = backBuffer;
                        backBuffer  = frontBuffer;
                        frontBuffer = temp;
                    }
                }
            };
            SurfaceMesh.DataSeries = dataSeries;
            _timer.Start();
            StartButton.IsEnabled = false;
            PauseButton.IsEnabled = true;
        }