【问题标题】:c# Update a datagrid view every 5 seconds with a background worker from a MySQL databasec# 使用 MySQL 数据库中的后台工作人员每 5 秒更新一次数据网格视图
【发布时间】:2018-08-17 03:51:15
【问题描述】:

这是我想要实现的目标: 我正在 c# (visual studio) 中以 windows 窗体格式构建警报系统。我有一个带有数据网格视图的 Windows 窗体,它需要每 5 秒从 MySQL 数据库中获取信息。我正在使用 System.Threading.Timer 和后台工作人员。我为此搜索了所有线程,但似乎没有任何效果。计时器正在工作,因为我每 5 秒出现一次线程错误,所以问题一定出在后台工作代码中。代码如下:

public partial class Alerts : Form
{
    private System.Threading.Timer _timerThread;
    private int _period = 5000;
    static BackgroundWorker bgw = new BackgroundWorker();

    public Alerts()
    {
        InitializeComponent();

        _timerThread = new System.Threading.Timer((o) =>
        {
            // Stop the timer;
            _timerThread.Change(-1, -1);


            bgw.DoWork += bgw_DoWork;
            bgw.RunWorkerAsync();


            // start timer again (BeginTime, Interval)
            _timerThread.Change(_period, _period);
        }, null, 0, _period);


    }

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        string constring = "datasource=localhost;port=3306;username=root;password=*******";
        MySqlConnection conDataBase = new MySqlConnection(constring);
        MySqlCommand cmdDataBase = new MySqlCommand(" select * from shopmanager.alerts ;", conDataBase);

        try
        {
            conDataBase.Open();
            MySqlDataAdapter sda = new MySqlDataAdapter();
            sda.SelectCommand = cmdDataBase;
            DataTable dbdataset = new DataTable();
            sda.Fill(dbdataset);
            BindingSource bsource = new BindingSource();

            bsource.DataSource = dbdataset;
            dataGridView1.DataSource = bsource;
            sda.Update(dbdataset);

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

    static void bgw_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
    {
        // I think this is where I should be able to update the datagridview but i'm not sure how.
    }
}

我完全迷路了。请帮忙

我现在尝试了这段代码,但它无法识别 DataGridView1。我做错了什么?

 public partial class Alerts : Form
{
    private System.Threading.Timer _timerThread;
    private int _period = 5000;
    static BackgroundWorker bgw = new BackgroundWorker();
    private static object dbdataset;

    public Alerts()
    {
        InitializeComponent();

        _timerThread = new System.Threading.Timer((o) =>
        {
            // Stop the timer;
            _timerThread.Change(-1, -1);


            // Calls UpdateAlerts() that updates a datagridview with the mysql data
            bgw.DoWork += bgw_DoWork;
            bgw.RunWorkerAsync();


            // start timer again (BeginTime, Interval)
            _timerThread.Change(_period, _period);
        }, null, 0, _period);


    }

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        string constring = "datasource=localhost;port=3306;username=root;password=******";
        MySqlConnection conDataBase = new MySqlConnection(constring);
        MySqlCommand cmdDataBase = new MySqlCommand(" select * from shopmanager.alerts ;", conDataBase);


        try
        {
            conDataBase.Open();
            MySqlDataAdapter sda = new MySqlDataAdapter();
            sda.SelectCommand = cmdDataBase;
            DataTable dbdataset = new DataTable();
            sda.Fill(dbdataset);
            BindingSource bsource = new BindingSource();

            bsource.DataSource = dbdataset;
            sda.Update(dbdataset);
            e.Result = dbdataset;

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

    static void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        DataGridView1.DataSource = dbdataset;
    }
}

【问题讨论】:

  • 您无法从DoWork 事件处理程序更新表单上的对象;您必须从 RunWorkerCompleted 更新它们。 DoWorkEventArgs e 对象有一个e.Result 属性,您可以在DoWork 中分配它(例如,使用dbdataset),然后在RunWorkerCompleted 中读取它。本教程可能会有所帮助:docs.microsoft.com/en-us/dotnet/framework/winforms/controls/…
  • 您应该查找 Invoke。并养成引用收到的错误消息的习惯!
  • 感谢您的回复,但我已经阅读了。我想知道的是如何正确编码(对于我的特殊情况)。谢谢

标签: c# mysql


【解决方案1】:

我会对您的代码进行一些更改:

  • 使用 Windows 窗体工具箱中的 Timer 而不是 System.Threading.Timer(它旨在更好地在 Windows 窗体中工作)。将其拖到表单上,然后将事件处理程序附加到其Tick 方法以获取定期更新。
  • 只附加一次BackgroundWorker 事件处理程序。
  • 将 BackgroundWorker 组件从设计器工具箱拖到表单上,以便为您管理其生命周期; 不要使用static字段。
  • 使用using 语句和MySqlConnection 来清理它使用的资源。
  • 使用实例方法(不是static),以便您可以引用Alerts 类中的属性/字段。

这是一个例子:

public partial class Alerts : Form
{
    public Alerts()
    {
        InitializeComponent();

        // set up BackgroundWorker once
        backgroundWorker1.DoWork += OnDoWork;
        backgroundWorker1.RunWorkerCompleted += OnRunWorkerCompleted;

        // set the timer and start it running
        timer1.Interval = 5000;
        timer1.Start();
        timer1.Tick += (o, e) => backgroundWorker1.RunWorkerAsync();
    }

    // This method will run in the background every five seconds. It can't
    // access parts of the form since it is on a background thread.
    private void OnDoWork(object sender, DoWorkEventArgs e)
    {
        using (MySqlConnection conDataBase = new MySqlConnection(connectionString))
        using (MySqlCommand cmdDataBase = new MySqlCommand(" select * from shopmanager.alerts;", conDataBase))
        {
            conDataBase.Open();
            MySqlDataAdapter sda = new MySqlDataAdapter { SelectCommand = cmdDataBase };
            DataTable dbdataset = new DataTable();
            sda.Fill(dbdataset);

            // return the results to the main form thread through this property
            e.Result = dbdataset;
        }
    }

    void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // This will run on the main form thread when the background work is
        // done; it connects the results to the data grid.
        dataGridView1.DataSource = e.Result;
    }
}

【讨论】:

【解决方案2】:
   public partial class Alerts : Form
   {
      #region Private Fields

      private static BackgroundWorker bgw = new BackgroundWorker();
      private int _period = 5000;
      private System.Threading.Timer _timerThread;

      #endregion Private Fields

      #region Public Constructors

      public Alerts()
      {
         InitializeComponent();
         bgw.DoWork += bgw_DoWork;
         bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;

         _timerThread = new System.Threading.Timer((o) =>
         {
            // Stop the timer;
            _timerThread.Change(-1, -1);
            // Calls UpdateAlerts() that updates a datagridview with the mysql data

            bgw.RunWorkerAsync();

            // start timer again (BeginTime, Interval)
            _timerThread.Change(_period, _period);
         }, null, 0, _period);
      }

      #endregion Public Constructors

      #region Private Methods

      private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
              DataGridView1.Invoke(new System.Action(() => 
    {DataGridView1.DataSource = e.Result;}));
      }

      private void bgw_DoWork(object sender, DoWorkEventArgs e)
      {
         string constring = "datasource=localhost;port=3306;username=root;password=******";
         MySqlConnection conDataBase = new MySqlConnection(constring);
         MySqlCommand cmdDataBase = new MySqlCommand(" select * from shopmanager.alerts ;", conDataBase);

         try
         {
            conDataBase.Open();
            MySqlDataAdapter sda = new MySqlDataAdapter();
            sda.SelectCommand = cmdDataBase;
            DataTable dbdataset = new DataTable();
            sda.Fill(dbdataset);
            BindingSource bsource = new BindingSource();

            bsource.DataSource = dbdataset;
            sda.Update(dbdataset);
            e.Result = dbdataset;
         }
         catch (Exception ex)
         {
            MessageBox.Show(ex.Message);
         }
         conDataBase.Close();
      }

      #endregion Private Methods
   }
  1. 您不需要在每次触发计时器时都订阅 DoWork 事件。
  2. 您永远不会订阅 RunWorkerCompleted 事件。
  3. 您应该将网格数据源分配给 e.Result,而不是 bgw 无法更新的私有属性
  4. 不确定这是否可行,您可能需要查看 Invoke。实际上,代码会抛出一个无效的跨线程操作或目标调用异常。您需要在网格控件上使用 Invoke。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多