In my multi threaded apps i need to do cross thread access on UI elements and i am using the thread safe methods to do that. I am repeatedly using this a lot in many of my projects and keeping them in the form file itself is making the file look ugly. So i want to create a seprate class where i can put all this and call them whenever needed but i am having trouble with it. For instace for changing the text element of a control i am using the following
delegate void SetTextCallback(string text, Control ctrl);
public void SetText(string text, Control ctrl)
{
if (ctrl.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text, ctrl });
}
else
{
if (ctrl.GetType() == typeof(Label))
{
ctrl.Text = text;
}
else
{
ctrl.Text += Environment.NewLine + text;
}
}
}
and call this function as
SetText("some text",label1);
This works fine if it is in the form class, if i put it into another class i am getting an error in the line
this.Invoke(d, new object[] { text, ctrl });
Can some one tell me how can i do this properly.
Also is it possible to have one UI accessor method do all the stuff, that is right now i am having multiple methods like this one to change the text one to change the enabled property one to change the back color and one to change the fore color. Is it possible to do it with something like
public void ChangePropert(Control ctrl,Property prop,Value val)
The problem with all this is you are starting to leak UI code outside of the form where the controls actually reside. A thread should not have to know about controls, it should do work and update the main thread and let the main thread worry about what needs to be done in the UI.
The way to accomplish this is have a callback that a second thread can call, but force that callback to actually be executed on the main thread instead of executed on the second thread. You can accomplish this by using the Synchronization context.
You need to wrap your secondary threads in a class that can keep a reference to the main thread synchronization context. Then the secondary threads can use this for call backs.
Example:
And your thread class will look something like this:
Now you can just get rid of all the invoke crap on every control.