【问题标题】:Update Graph while picking values from the database从数据库中选择值时更新图表
【发布时间】:2013-07-16 00:28:35
【问题描述】:

我正在尝试从数据库中挑选值并从那里不断更新图表。使用How to update the GUI from another thread in C#? 我的代码是:

private void button1_Click(object sender, EventArgs e)
        {
                string myConnection = "datasource=localhost;port=3306;username=root;password=root";
                MySqlConnection conDataBase = new MySqlConnection(myConnection);
                MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
                MySqlDataReader myReader;
                this.Invoke((MethodInvoker)delegate
                {
                    try
                    {
                        conDataBase.Open();
                        myReader = cmdDataBase.ExecuteReader();

                        while (myReader.Read())
                        {
                            this.chart1.Series["Series1"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));

                        }

                        conDataBase.Close();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                });
        }

虽然我没有收到任何错误,但我不认为它的工作是因为图表是恒定/静态的。 有什么建议。 我基本上想要的是这个图表会根据数据库中的新值不断更新......类似于心跳监视器或类似的效果。

任何建议...问候

编辑:我也尝试使用后台工作人员,但在按钮单击时我也得到以下信息:

Cross thread operation not valid: Control 'charTemperature' accessed from athread other than the thread it was created on

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.Threading;

namespace project
{
    public partial class Form2 : Form
    {

        private BackgroundWorker bw = new BackgroundWorker();

        public Form2()
        {
            InitializeComponent();
            bw.WorkerSupportsCancellation = true;
            bw.WorkerReportsProgress = false;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);

        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnTemperature_Click(object sender, EventArgs e)
        {
            if (bw.IsBusy != true)
            {
                bw.RunWorkerAsync();
            }


            //this.Invoke((MethodInvoker)delegate
           // {
            /*    string myConnection = "datasource=localhost;port=3306;username=root;password=root";
                MySqlConnection conDataBase = new MySqlConnection(myConnection);
                MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
                MySqlDataReader myReader;
                    try
                    {
                        conDataBase.Open();
                        myReader = cmdDataBase.ExecuteReader();

                        while (myReader.Read())
                        {
                            this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));

                        }

                        conDataBase.Close();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                //});*/
        }

        private void btnStopUpdating_Click(object sender, EventArgs e)
        {
            if (bw.WorkerSupportsCancellation == true)
            {
                bw.CancelAsync();
            }
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            while (true)
            {
                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    string myConnection = "datasource=localhost;port=3306;username=root;password=root";
                    MySqlConnection conDataBase = new MySqlConnection(myConnection);
                    MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
                    MySqlDataReader myReader;
                    try
                    {
                        conDataBase.Open();
                        myReader = cmdDataBase.ExecuteReader();

                        while (myReader.Read())
                        {
                            this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));
                            System.Threading.Thread.Sleep(1000);

                        }

                        conDataBase.Close();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        private void Form2_Load(object sender, EventArgs e)
        {

        }


    }
}

又一次徒劳的尝试……点击按钮没有任何反应……

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using System.Threading;


namespace project
{
    public partial class Form2 : Form
    {

        private BackgroundWorker bw = new BackgroundWorker();

        public string vdatetime;
        public Int32 vtemp;

        public Form2()
        {
            InitializeComponent();
            bw.WorkerSupportsCancellation = true;
           // bw.WorkerReportsProgress = false;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);


        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnTemperature_Click(object sender, EventArgs e)
        {
            //if (bw.IsBusy != true)
            //{
                this.bw.RunWorkerAsync();
            //}


            //this.Invoke((MethodInvoker)delegate
           // {
            /*    string myConnection = "datasource=localhost;port=3306;username=root;password=root";
                MySqlConnection conDataBase = new MySqlConnection(myConnection);
                MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
                MySqlDataReader myReader;
                    try
                    {
                        conDataBase.Open();
                        myReader = cmdDataBase.ExecuteReader();

                        while (myReader.Read())
                        {
                            this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));

                        }

                        conDataBase.Close();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                //});*/
        }

        private void btnStopUpdating_Click(object sender, EventArgs e)
        {
           // if (bw.WorkerSupportsCancellation == true)
            //{
                this.bw.CancelAsync();
            //}
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

                if ((worker.CancellationPending == true))
                {
                    e.Cancel = true;
                    //break;
                }
                else
                {
                    string myConnection = "datasource=localhost;port=3306;username=root;password=root";
                    MySqlConnection conDataBase = new MySqlConnection(myConnection);
                    MySqlCommand cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
                    MySqlDataReader myReader;
                    try
                    {
                        conDataBase.Open();
                        myReader = cmdDataBase.ExecuteReader();
                        //this.Invoke((MethodInvoker)delegate
                        //{

                            while (myReader.Read())
                            {
                                vdatetime = myReader.GetString("datetime");
                                vtemp = myReader.GetInt32("temp");
                                //Thread.Sleep(300);

    //                            this.chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));
  //                              System.Threading.Thread.Sleep(1000);

                            }

                            conDataBase.Close();
//                        });
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }


                }
        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // The user canceled the operation.
                MessageBox.Show("Operation was canceled");
            }
            else if (e.Error != null)
            {
                // There was an error during the operation. 
                string msg = String.Format("An error occurred: {0}", e.Error.Message);
                MessageBox.Show(msg);
            }
            else
            {
                 this.chartTemperature.Series["Temperature"].Points.AddXY(vdatetime, vtemp);
            }
        }
        private void Form2_Load(object sender, EventArgs e)
        {

        }

    }
}

【问题讨论】:

    标签: c# multithreading winforms visual-studio-2010 invoke


    【解决方案1】:

    假设您无法将更改通知推送到客户端,您可能需要某种轮询方法。

    您可以设置一个计时器(参见下面的链接)并每隔一段时间查询新数据。
    http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

    我不确定您使用的是哪种图表,但您可以在系列末尾添加新点(并从系列前面删除旧点),这可能会给您类似你提到的心跳监测效果...(如果图表不支持你可能需要重建它,或者在每次更新时给它一个全新的系列)

    您可能希望调整您正在使用的查询,以便在每次调用时仅获得新数据点。(其中 datetime > [在先前调用中已检索到的最大日期时间])

    实际执行 UI 更新的代码仍然可以通过调用(..)调用,如您的问题中所述...

    【讨论】:

    • 我不想使用计时器...我需要使用 Invoke 或 BackgroundWorker
    • 您可以使用 Invoke...但就其本身而言,这只会导致代码运行一次...您还需要一些东西来触发可以使用计时器的定期更新(除非您要附加一些其他周期性事件)...计时器事件可以调用 Invoke 代码...如果您想将数据检索推送到另一个线程(并且您可以触发一次 UI 刷新),可以使用 BackgroundWorker工人完成)..
    • 查看更新的问题..我可以看到您在后台工作人员中有一个循环和睡眠...您需要在正确的线程上获取 UI 更新代码...您可以在 DoWork 方法中的 this.chartTemperature 更改周围尝试 Invoke 调用......但是我认为这是对 BackgroundWorker 的不寻常使用(基本上循环和睡眠使它像一个计时器一样)
    【解决方案2】:

    好的,这样做:

    使用系统; 使用 System.Collections.Generic; 使用 System.ComponentModel; 使用 System.Data; 使用 System.Drawing; 使用 System.Linq; 使用 System.Text; 使用 System.Windows.Forms; 使用 MySql.Data.MySqlClient; 使用 System.Threading;

    命名空间项目 { 公共部分类Form2:表格 {

        public delegate void AddGraphPointsTemp();
        public AddGraphPointsTemp myDelegate1;
        Thread tempThread;
        string myConnection;
        MySqlConnection conDataBase;
        MySqlCommand cmdDataBase;
        MySqlDataReader myReader;
    
    
        public Form2()
        {
            InitializeComponent();
    
            myDelegate1 = new AddGraphPointsTemp(AddGraphPointsMethodTemp);
            myConnection = "datasource=localhost;port=3306;username=root;password=root";
            conDataBase = new MySqlConnection(myConnection);
            cmdDataBase = new MySqlCommand(" select * from data.test; ", conDataBase);
            conDataBase.Open();
            myReader = cmdDataBase.ExecuteReader();
    
    
        }
    
        private void btnExit_Click(object sender, EventArgs e)
        {
            conDataBase.Close();
            Application.Exit();
        }
    
        public void AddGraphPointsMethodTemp()
        {
            try
            {
    
                    myReader.Read();
                    chartTemperature.Series["Temperature"].Points.AddXY(myReader.GetString("datetime"), myReader.GetInt32("temp"));
                    chartTemperature.Update();
    
    
    
    
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
    
    
        }
    
        private void btnTemperature_Click(object sender, EventArgs e)
        {
            tempThread = new Thread(ThreadFunction1);
            tempThread.Start(this);
    
        }
    
    
        public static void ThreadFunction1(Object obj)
        {
            while (true)
            {
                Form2 myForm2 = (Form2)obj;
                myForm2.Invoke(myForm2.myDelegate1);
                Thread.Sleep(300);
            }
        }
    
    
        private void Form2_Load(object sender, EventArgs e)
        {
    
        }
    
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2014-01-25
      • 2012-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多