// sets the raw data for the given control, invokes on main thread
 public void UpdateImageControlContents(int index, PixelFormat pf, params float[][] buffers)
 {
     this.Invoke(new Action(() =>
     {
         if (imageFlowPanel.Controls.Count > index)
         {
             ImageControl ic = imageFlowPanel.Controls[index] as ImageControl;
             ic.Format       = pf;
             for (int k = 0; k < buffers.Length; k++)
             {
                 ic.SetImage(k, buffers[k]);
             }
             ic.Invalidate();
         }
     }));
 }
        private void AsyncUpdate()
        {
            DateTime prev = DateTime.Now;
            double time_since_last_draw = 0;

            bool parent_previously_visible = false;
            bool drawn_atleast_once = false;

            while (true)
            {
                // update last time since last draw
                DateTime now = DateTime.Now;
                time_since_last_draw += now.Subtract(prev).TotalSeconds;
                prev = now;

                // get a command message if there is one
                Message m = _messages.Dequeue();
                if (m != null)
                {
                    switch (m.Type)
                    {
                        case "Start":
                            switch (_current_state)
                            {
                                case State.Paused:
                                    _current_state = State.Running;
                                    break;
                                case State.Running:
                                    break;
                                case State.Stopped:
                                    // image controls need to be added and modified on the main thread, so do an Invoke
                                    this.Invoke(new Action(() =>
                                    {
                                        int image_width = this.ImageControlWidth;
                                        int image_height = this.ImageControlHeight;
                                        PixelFormat pixel_format = this.ImageControlPixelFormat;

                                        for (int k = 0; k < this.ImageControlCount; k++)
                                        {
                                            ImageControl ic = new ImageControl(_count, image_width, image_height, _scale, pixel_format);
                                            imageFlowPanel.Controls.Add(ic);
                                        }
                                        this._current_state = State.Running;
                                    }));

                                    break;
                            }
                            break;
                        case "Pause":
                            // pausing just
                            _current_state = State.Paused;
                            break;
                        case "Stop":
                            // stop the visualizer and clear out the images on the main thread
                            _current_state = State.Stopped;
                            drawn_atleast_once = false;
                            this.Invoke(new Action(() =>
                            {
                                this.imageFlowPanel.Controls.Clear();
                            }));
                            break;
                        case "Zoom":
                            // update image controls on the main thread
                            var delta = (int)m["delta"];
                            // scale must be at least 1
                            _scale = Math.Max(delta + _scale, 1);
                            UpdateImageControlDimensions();
                            break;
                    }
                }
                else
                {
                    // sleep when the message queue is empty
                    Thread.Sleep(50);
                }

                if (_current_state == State.Running && drawn_atleast_once == false)
                {
                    drawn_atleast_once = true;
                    time_since_last_draw = 0.0;
                    Drawing();
                    prev = DateTime.Now;
                }

                if (_current_state == State.Running && time_since_last_draw >= DrawInterval)
                {
                    if (this.Parent != null && this.Parent.Visible == true)
                    {
                        if (parent_previously_visible == false)
                        {
                            // sleep awhile before drawing if we just flipped to this tab
                            Thread.Sleep(500);
                        }

                        // reset time_since_last_draw and update
                        time_since_last_draw = 0.0;
                        Drawing();
                        prev = DateTime.Now;
                    }
                    parent_previously_visible = this.Parent != null ? this.Parent.Visible : false;
                }

            }
        }
        private void AsyncUpdate()
        {
            DateTime prev = DateTime.Now;
            double   time_since_last_draw = 0;

            bool parent_previously_visible = false;
            bool drawn_atleast_once        = false;

            while (true)
            {
                // update last time since last draw
                DateTime now = DateTime.Now;
                time_since_last_draw += now.Subtract(prev).TotalSeconds;
                prev = now;

                // get a command message if there is one
                Message m = _messages.Dequeue();
                if (m != null)
                {
                    switch (m.Type)
                    {
                    case "Start":
                        switch (_current_state)
                        {
                        case State.Paused:
                            _current_state = State.Running;
                            break;

                        case State.Running:
                            break;

                        case State.Stopped:
                            // image controls need to be added and modified on the main thread, so do an Invoke
                            this.Invoke(new Action(() =>
                            {
                                int image_width          = this.ImageControlWidth;
                                int image_height         = this.ImageControlHeight;
                                PixelFormat pixel_format = this.ImageControlPixelFormat;

                                for (int k = 0; k < this.ImageControlCount; k++)
                                {
                                    ImageControl ic = new ImageControl(_count, image_width, image_height, _scale, pixel_format);
                                    imageFlowPanel.Controls.Add(ic);
                                }
                                this._current_state = State.Running;
                            }));

                            break;
                        }
                        break;

                    case "Pause":
                        // pausing just
                        _current_state = State.Paused;
                        break;

                    case "Stop":
                        // stop the visualizer and clear out the images on the main thread
                        _current_state     = State.Stopped;
                        drawn_atleast_once = false;
                        this.Invoke(new Action(() =>
                        {
                            this.imageFlowPanel.Controls.Clear();
                        }));
                        break;

                    case "Zoom":
                        // update image controls on the main thread
                        var delta = (int)m["delta"];
                        // scale must be at least 1
                        _scale = Math.Max(delta + _scale, 1);
                        UpdateImageControlDimensions();
                        break;
                    }
                }
                else
                {
                    // sleep when the message queue is empty
                    Thread.Sleep(50);
                }

                if (_current_state == State.Running && drawn_atleast_once == false)
                {
                    drawn_atleast_once   = true;
                    time_since_last_draw = 0.0;
                    Drawing();
                    prev = DateTime.Now;
                }

                if (_current_state == State.Running && time_since_last_draw >= DrawInterval)
                {
                    if (this.Parent != null && this.Parent.Visible == true)
                    {
                        if (parent_previously_visible == false)
                        {
                            // sleep awhile before drawing if we just flipped to this tab
                            Thread.Sleep(500);
                        }

                        // reset time_since_last_draw and update
                        time_since_last_draw = 0.0;
                        Drawing();
                        prev = DateTime.Now;
                    }
                    parent_previously_visible = this.Parent != null ? this.Parent.Visible : false;
                }
            }
        }