Link to home
Start Free TrialLog in
Avatar of r_pat72
r_pat72

asked on

Implmenting Threading (in Winforms C#)- Getting Error - Cross-thread operation not valid

Hi,

 

I am trying to implement Threading in my application. One of my method ia taking 2 to 3 mins time for getting data from SQL Server. So I have Implemented Threading for this.

 

But I am getting error InvalidOperation Exception -  Cross-thread operation not valid: Control 'dataGridView1' accessed from a thread other than the thread it was created on.

 

Here is my sample code.

 

public partial class frmEmployee : Form

{

public frmEmployee()

{

InitializeComponent();

}

 

protected override void OnLoad(EventArgs e)

{


base.OnLoad(e);

}

private void button1_Click(object sender, EventArgs e)

{


ThreadPool.QueueUserWorkItem(new WaitCallback(GetEmployeeData));


}

private void GetEmployeeData(Object stateInfo)

{

DataAccessLayer db = new DataAccessLayer();

System.Linq.IQueryable<Employee> emp = db.GetEmployee();

dataGridView1.DataSource = emp;


}

private void EmployeeData()

{

DataAccessLayer db = new DataAccessLayer();

System.Linq.IQueryable<Employee> emp = db.GetEmployee();

dataGridView1.DataSource = emp;

}

private void button2_Click(object sender, EventArgs e)

{

SecondMethod();

}

private static void SecondMethod()

{

MessageBox.Show("This is my second test message");

}

}

 

After clicking Button1, I clicked Button2 which display me the message "This is my second test message".

But after that I am getting, Cross-thread operation not valid.

 

Please help me with this.

 

Thanks!!!

public partial class frmEmployee : Form
 
{
 
public frmEmployee()
 
{
 
InitializeComponent();
 
}
 
 
 
protected override void OnLoad(EventArgs e)
 
{
 
 
base.OnLoad(e);
 
}
 
private void button1_Click(object sender, EventArgs e)
 
{
 
 
ThreadPool.QueueUserWorkItem(new WaitCallback(GetEmployeeData));
 
 
}
 
private void GetEmployeeData(Object stateInfo)
 
{
 
DataAccessLayer db = new DataAccessLayer();
 
System.Linq.IQueryable<Employee> emp = db.GetEmployee();
 
dataGridView1.DataSource = emp;
 
 
}
 
private void EmployeeData()
 
{
 
DataAccessLayer db = new DataAccessLayer();
 
System.Linq.IQueryable<Employee> emp = db.GetEmployee();
 
dataGridView1.DataSource = emp;
 
}
 
private void button2_Click(object sender, EventArgs e)
 
{
 
SecondMethod();
 
}
 
private static void SecondMethod()
 
{
 
MessageBox.Show("This is my second test message");
 
}
 
}

Open in new window

Avatar of philipjonathan
philipjonathan
Flag of New Zealand image

I think the problem is with line 42
dataGridView1.DataSource = emp;

I don't think you can data bind a datagrid on a thread other than the thread where the control was created. You might want to perform data binding inside the OnLoad override, and just refresh the data (query from data source) during GetEmployeeData().
It is illegal to make cross thread calls to the UI thread as far as I know, but You should be abe to override the default behaivor using:

private void GetEmployeeData(Object stateInfo)
 {
// Disable the checking for illegal crossthread calls
Control.CheckForIllegalCrossThreadCalls = false;
// Rest of code...
 DataAccessLayer db = new DataAccessLayer();
 System.Linq.IQueryable<Employee> emp = db.GetEmployee();
 dataGridView1.DataSource = emp;
 }

Just add the extra line to all method making cross thread calls. But notice that this is NOT the best solution, it's simply disabling the checking.
/Carl.
ASKER CERTIFIED SOLUTION
Avatar of margajet24
margajet24
Flag of Singapore image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
when updating controls on a separate thread, check first InvokeRequired because directly updating the properties of the control on another thread is not allowed.
margajet24 is absolutely correct, I'm a VB guy, don't know the actual implementation i C#...