I have a function
public void ShowAllFly()
{
cbFly.Items.Clear();
cbFly.Items.Add("Uçuş Seçiniz...");
dsFlyTableAdapters.tblFlyTableAdapter _t=new KTHY.dsFlyTableAdapters.tblFlyTableAdapter();
dsFly _mds = new dsFly();
_mds.EnforceConstraints = false;
dsFly.tblFlyDataTable _m = _mds.tblFly;
_t.Fill(_m);
foreach (DataRow _row in _m.Rows)
{
cbFly.Items.Add(_row["FlyID"].ToString()+"-"+_row["FlyName"].ToString() + "-" + _row["FlyDirection"].ToString() + "-" + _row["FlyDateTime"].ToString());
}
_Thread.Abort();
timer1.Enabled = false;
WaitPanel.Visible = false;
}
In Form_Load Function Like this;
{
_Thread = new System.Threading.Thread(new System.Threading.ThreadStart(ShowAllFly));
_Thread.Start();
_Thread.Priority = System.Threading.ThreadPriority.Normal;
}
But When I run it;
in ShowAllFly function
cbFly.Items.Clear(); ---- HERE Gives ERROR LIKE Control.Invoke must be used to interact with controls created on a separate thread.
What is the problem?
Invoke() makes sure that the invoked method will be invoked on the UI thread. This is useful when you want to make an UI adjustment in another thread (so, not the UI thread). InvokeRequired checks whether you need to use the Invoke() method.
Invoke : Executes on the UI thread, but calling thread waits for completion before continuing. Control. BeginInvoke : Executes on the UI thread, and calling thread doesn't wait for completion.
There are two golden rules of threading in Windows Forms:
In order to interact with the UI from a different thread, you need to "marshall" the call to the UI thread, using a delegate and calling Control.Invoke
/BeginInvoke
. You can test whether or not you need to call Invoke
using the InvokeRequired
property, but these days I personally tend to just do it anyway - there's not much penalty for invoking when you don't need to.
Lambda expressions in C# 3 (or anonymous methods in C# 2) make this a lot more pleasant as well.
For instance, you could use:
cbFly.Invoke((MethodInvoker)(() => cbFly.Items.Clear()));
All the brackets get in the way a bit, so you might want to add an extension method like this, if you're using C# 3:
public static void Invoke(this Control control, MethodInvoker action)
{
control.Invoke(action);
}
Then you could do:
cbFly.Invoke(() => cbFly.Items.Clear());
which is a good deal simpler. Usually you can get away with using a MethodInvoker
by capturing any variables you need to access within the delegate.
See my threading tutorial or Joe Albahari's for more details.
As a secondary matter, I see you're using Thread.Abort
- in fact on your own thread, despite it having other calls after it. Why? Aborting any thread other than your own is an "emergencies only" type call (which should usually be followed by the app being unloaded anyway) and I can't see any reason to abort the current thread when there's still work to be done afterwards...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With