0

I am having a backgroundworker issue - I am new to threading so I am trying to get this done as painlessly as possible.

My main issue is the end users will only have .NET 4.0 so I cannot use await / async and been told BGW is the best thing for the framework I am using.

I have a "Please Wait" form with a gif animation that I would like to load while the datagridview is being populated. I need to somehow do a check to make sure it has finished populating to close the "Please Wait" down but am a bit stuck on how to achieve this.

    public void btnSearch_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
        Application.DoEvents();
        try
        {
            this.TestDataTableAdapter.Fill(this.TesteDataData.TestDataTable, txtHotName.Text, ((System.DateTime)(System.Convert.ChangeType(txtDepartFrom.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtDepartTo.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtBookFrom.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtBookTo.Text, typeof(System.DateTime)))));
            int RowC = TestDataTableDataGridView.RowCount;
            if (RowC == 0)
            {
                MessageBox.Show(GlobVar.NoResults, "", MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }
        catch (System.Exception exc)
        {
            MessageBox.Show
                (
                "Problem" +
                exc.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Warning
                );
        }
        finally
        {
            //pleaseWait.Close();
        }

This is my button to load the data in to my DataGridView. And so far this is my DoWork event

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        pleaseWait.ShowDialog();
    }

The finally will not work due to cross threading ( so comment out currently ) but I need to do a loop/check to find out if the DataGridView has been filled and action is complete to then close the DoWork. Or some how force it to jump to RunWorkerCompleted then I can just put a pleaseWait.Close(); in there instead.

Any suggestions please?

Zoltan
  • 93
  • 7
  • what about shooting an event at the end of the task? – Sebastian L Mar 29 '17 at 09:48
  • 1
    You must show your `pleaseWait` dialog in your main ui thread,not in the `backgroundWorker1.DoWork`, and hide it in the `RunWorkerCompleted` event of the `backgroundWorker1`. Is the `this.TestDataTableAdapter.Fill` part the one that should go in the `backgroundWorker1.DoWork` – Pikoh Mar 29 '17 at 09:50

1 Answers1

1

You must show your pleaseWait dialog in your main ui thread,not in the backgroundWorker1.DoWork, and hide it in the RunWorkerCompleted event of the backgroundWorker1. Is the this.TestDataTableAdapter.Fill part the one that should go in the backgroundWorker1.DoWork, so your code should look more or less like this:

public void btnSearch_Click(object sender, EventArgs e)
{
    pleaseWait.ShowDialog();
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        this.TestDataTableAdapter.Fill(this.TesteDataData.TestDataTable, txtHotName.Text, ((System.DateTime)(System.Convert.ChangeType(txtDepartFrom.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtDepartTo.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtBookFrom.Text, typeof(System.DateTime)))), ((System.DateTime)(System.Convert.ChangeType(txtBookTo.Text, typeof(System.DateTime)))));

    }
    catch (System.Exception exc)
    {
        //You can't show a messagebox here,as it is not in the UI thread
    }
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pleaseWait.Close();
    int RowC = TestDataTableDataGridView.RowCount;
    if (RowC == 0)
    {
            MessageBox.Show(GlobVar.NoResults, "", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    }
}

Of course, in this code you have a problem, as the TestDataTableAdapter.Fill code won't work because you are trying to access some TextBoxes and you can't from another thread.

You have several solutions to this. You could use some variables to read the values before calling the backgroundworker, and accessing this variables instead of the TextBoxes. Or you could call the backgroundworker with parameters.

I recommend you to read more about BackGroundWorker, for example in MSDN. Or this question about sending parameters to a BackgroundWorker.

Community
  • 1
  • 1
Pikoh
  • 7,582
  • 28
  • 53