C#从BackgroundWorker更新DataGridView

时间:2018-10-25 14:51:51

标签: c# backgroundworker

仍然努力将实时数据从我的数据库获取到datagridview。这次,我尝试通过后台工作人员执行此操作。它从doWork方法提供的唯一内容是backgroundWorker1_ProgressChanged方法的INT。我也想向其发送诸如DataTable之类的对象,因此我可以刷新主线程Form1上的数据。如何将对象传递给backgroundWorker1_ProgressChanged事件?在代码中标记了我需要来自DoWork的数据的位置

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        string IP_db_mysql = "1";
        string Port_db__mysql = "1";
        string UserName_db__mysql = "1";
        string Password_db__mysql = "1";
        string dbName__mysql = "1";

        string connString = "Server =" + IP_db_mysql + "; Port =" + Port_db__mysql + "; Database =" + dbName__mysql + "; Uid =" + UserName_db__mysql + ";Pwd =" + Password_db__mysql + ";";
        MySqlConnection conn = new MySqlConnection();
        DataTable dt = new DataTable();

        string query = "SELECT * FROM mysql.test_table;";

        int sum = 0;

        for (int i = 1; i <= 10; i++)
        {
            sum = sum + i;

            try
            {
                // open connectipon
                conn.ConnectionString = connString;
                conn.Open();

                // build command
                MySqlCommand cmd = new MySqlCommand(query, conn);

                // execute command
                MySqlDataReader dataReader = cmd.ExecuteReader();

                // fill datatable
                dt.Load(dataReader);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                conn.Close();
            }

            // Calling ReportProgress() method raises ProgressChanged event
            // To this method pass the percentage of processing that is complete
            backgroundWorker1.ReportProgress(i);

            Thread.Sleep(100);

            // Check if the cancellation is requested
            if (backgroundWorker1.CancellationPending)
            {
                // Set Cancel property of DoWorkEventArgs object to true
                e.Cancel = true;
                // Reset progress percentage to ZERO and return
                backgroundWorker1.ReportProgress(0);
                return;
            }
        }

        // Store the result in Result property of DoWorkEventArgs object
        e.Result = sum;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        labelProgress.Text = e.ProgressPercentage.ToString() + "%";
     **----------->>   dataGridView1.DataSource = HOW TO GET DATATABLE FROM DO WORK METHOD !?  <<------------------------**
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            labelProgress.Text = "Processing cancelled";
        }
        else if (e.Error != null)
        {
            labelProgress.Text = e.Error.Message;
        }
        else
        {
            labelProgress.Text = e.Result.ToString();
        }
    }

    private void button23_Click(object sender, EventArgs e)
    {
        // Check if the backgroundWorker is already busy running the asynchronous operation
        if (!backgroundWorker1.IsBusy)
        {
            // This method will start the execution asynchronously in the background
            backgroundWorker1.RunWorkerAsync();
        }
    }

    private void button24_Click(object sender, EventArgs e)
    {
        if (backgroundWorker1.IsBusy)
        {
            // Cancel the asynchronous operation if still in progress
            backgroundWorker1.CancelAsync();
        }
    }

2 个答案:

答案 0 :(得分:1)

使用下面的代码之类的状态对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Data;

namespace ConsoleApplication76
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
    public enum ReportTypes
    {
        PROGRESS,
        DATATABLE
    }
    public class Report
    {
        public int progress { get; set; }
        public ReportTypes type { get; set; }
        public DataTable table { get; set; }
    }
    public class Worker
    {
        public BackgroundWorker backgroundWorker1 { get; set; }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            Report report = new Report();
            report.progress = 50;
            report.type = ReportTypes.PROGRESS;
            backgroundWorker1.ReportProgress(50, report);

            DataTable dt = new DataTable();
            report.table = dt;
            report.type = ReportTypes.DATATABLE;
            backgroundWorker1.ReportProgress(50, report);
        }


        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
           int progress = e.ProgressPercentage;
           Report report =  e.UserState as Report;

           switch (report.type)
           {
               case ReportTypes.PROGRESS :
                  BeginInvoke((MethodInvoker)delegate
                  {
                    WriteStatusAndError("Query Completed");
                  });
                   break;
               case ReportTypes.DATATABLE :
                   break;
           }
       }


    }
}

答案 1 :(得分:1)

在BackgroundWorker的DoWork的末尾,您需要将其DataSource设置为结果。但是,由于您直接在后台工作,因此您将获得异常,因为WinForms不允许您从另一个线程访问UI。

您可以使用以下代码执行此操作:

// create a method to handle updating the datasource
public void UpdateDataGridViewSource(object data)
{
    // check if we need to swap thread context
    if(this.dataGridView1.InvokeRequired)
    {
        // we aren't on the UI thread. Ask the UI thread to do stuff.
        this.dataGridView1.Invoke(new Action(() => UpdateDataGridViewSource(data)));
    }
    else
    {
        // we are on the UI thread. We are free to touch things.
        this.dataGridView1.DataSource = data;
        this.dataGridView1.DataBind();
    }
}

// at the end of your DoWork()
this.UpdateDataGridViewSource(result);