I am filling a DataGridView
by running a SQL query with BackgroundWorker
. My code works perfectly if I run it directly in a button event handler, but when I put in a DoWork
BackgroundWorker it doesn't update the UI. My code is below.
DataTable tab1table = new DataTable();
public Form1()
{
InitializeComponent();
Instantiatesearch1Thread();
}
private void Instantiatesearch1Thread()
{
search1Thread.WorkerReportsProgress = true;
search1Thread.WorkerSupportsCancellation = true;
search1Thread.ProgressChanged += search1Thread_ProgressChanged;
search1Thread.DoWork += search1Thread_Dowrk;
search1Thread.RunWorkerCompleted += search1Thread_RunWorkerCompleted;
}
private void sbutton1_Click(object sender, EventArgs e)
{
search1Thread.RunWorkerAsync();
}
void search1Thread_Dowrk(object sender, DoWorkEventArgs e)
{
int percentprogress = 0;
percentprogress++;
Thread.Sleep(1000);
// Search1 button event handler
using (SqlConnection conn = new SqlConnection(connectionstring))
{
conn.Open();
using (SqlDataAdapter cmd = new SqlDataAdapter(comboBox1SQL, conn))
{
if (comboBox1.Text.Contains("ID"))
{
long para = long.Parse(search1.Text);
cmd.SelectCommand.Parameters.Add(new SqlParameter
{
ParameterName = "@combo1Par",
Value = para,
SqlDbType = SqlDbType.BigInt
});
}
else if (comboBox1.Text.Contains("Other Thing") || comboBox1.Text.Contains("Other Stuff"))
{
string para = search1.Text;
cmd.SelectCommand.Parameters.Add(new SqlParameter
{
ParameterName = "@combo1Par",
Value = "%" + para + "%",
SqlDbType = SqlDbType.NVarChar,
});
}
// Clear datatable if it contains any information and then fill it
// tab1datatable is a DataGridView
if (tab1table != null)
tab1table.Clear();
cmd.Fill(tab1table);
//tab1datatable.DataSource = tab1table;
// A bunch of expensive calculations
}
}
}
void search1Thread_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
search1Progress.Value = e.ProgressPercentage;
}
void search1Thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
tab1datatable.DataSource = tab1table;
tab1datatable.Refresh();
MessageBox.Show("All Done!");
}
By using a MessageBox
I discovered that the code is not accessing the if comboBox1.Text.Contains()
statements, which I think makes sense, because that information comes from the UI and BackgroundWorker
can't directly access the UI. This would also explain why then tab1datatable
and tab1table
go untouched.
I think I need to use the Invoke
method somewhere, but I am not sure how. I took a look at c# - Pass information to BackgroundWorker From UI during execution but it doesn't really answer my question. If Invoke
is what I need, how do I implement in this code to allow it to grab information from the UI and subsequently update it with the filled DataGridView
?