Patrick Patrick - 9 days ago 7
C# Question

Generating Report in C# causing error

I'm generating report in C# by using background worker but I'm getting this error.

enter image description here

Source code as follows:


  • I have to access my datagridview Records to access it's data.

  • A small window opens up in my datagridview which asks user to enter date from and to generate report, then i access back my datagridview convert into data table write in XML file and generate report.



Global Variables

// This is the form where the data lies, I'm accessing it's instance.
Records TR = new Records();
// This is the form where report will be displayed.
TReportDisplay TRD = new TReportDisplay();
// This is the report.
Treport treport1 = new Treport();

private void button1_Click(object sender, EventArgs e)
{
// FIXED HERE - 1
// FIXED - 2 IN THE ANSWER BELOW.
// Accessing my DataGridView Form Instance.
TR = Application.OpenForms.OfType<Records>().ElementAt(0);
treport1.SetDataSource(TR.ds);
TRD.crystalReportViewer2.ReportSource = treport1;

backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

try
{

TRD.crystalReportViewer2.ReportSource = treport1;
ParameterFieldDefinitions Parameters;
ParameterFieldDefinition Parameter;
ParameterValues Values = new ParameterValues();
ParameterDiscreteValue DiscreteValue = new ParameterDiscreteValue();

DiscreteValue.Value = dateTimePicker1.Text;
Parameters = treport1.DataDefinition.ParameterFields;
Parameter = Parameters["fromdate"];
Values = Parameter.CurrentValues;
Values.Clear();
Values.Add(DiscreteValue);
Parameter.ApplyCurrentValues(Values);
DiscreteValue.Value = dateTimePicker2.Text;
Parameters = treport1.DataDefinition.ParameterFields;
Parameter = Parameters["todate"];
Values = Parameter.CurrentValues;
Values.Add(DiscreteValue);
Parameter.ApplyCurrentValues(Values);

}
}
catch (Exception ex) { MessageBox.Show(ex.Message.ToString(), "Message"); };
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{

}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
TRD.ShowDialog();
}


There were two issues, first of all updating progress bar from a different thread for which I got answer, another calling form instance after background worker was causing the issue, just put the variable before and fixed.

Answer

The error message is telling you that the only way to update the controls is via the thread that the controls are running on. You are currently running on a different thread (the one for the back ground worker).

Take a look at the example in this link for another question on SO Invoke(Delegate) . You basically should have a method that you can call, to update the UI, which can check if it is on the correct thread and if it is not gets the correct thread to call it.

This is a snippet of code that was on the link parvee gave above that shows how you can do this.

public void UpdateProgress(int percentComplete)
{
   if (!InvokeRequired)
   {
      ProgressBar.Value = percentComplete;
   }
   else
   {
      Invoke(new Action<int>(UpdateProgress), percentComplete);
   }
}
Comments