简体   繁体   English

C#从BackgroundWorker更新DataGridView

[英]C# Update DataGridView from BackgroundWorker

Still struggling to get live data from my database to datagridview. 仍在努力将实时数据从我的数据库获取到datagridview。 This time I am attempting to do it via background worker. 这次,我尝试通过后台工作人员执行此操作。 The only thing it gives from doWork method is an INT for backgroundWorker1_ProgressChanged method. 它从doWork方法提供的唯一内容是backgroundWorker1_ProgressChanged方法的INT。 I want to send my objects such as DataTable to it as well, so I could refresh data which is on main thread Form1. 我也想向其发送诸如DataTable之类的对象,因此我可以刷新主线程Form1上的数据。 How can I pass my objects to backgroundWorker1_ProgressChanged event? 如何将对象传递给backgroundWorker1_ProgressChanged事件? Marked the place in the code where I need the data from DoWork 在代码中标记了我需要来自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();
        }
    }

Use a state object like code below 使用下面的代码之类的状态对象

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;
           }
       }


    }
}

At the end of your BackgroundWorker's DoWork you need to set its DataSource to your result. 在BackgroundWorker的DoWork结束时,您需要将其DataSource设置为结果。 However, since you're in a background worker if you do that directly you'll get an exception because WinForms won't let you access the UI from another thread. 但是,由于您直接在后台工作,因此您将获得异常,因为WinForms不允许您从另一个线程访问UI。

You can do this with the following code: 您可以使用以下代码执行此操作:

// 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM