Reputation: 4293
I found that running a thread is really isolated to a big degree from the main application. You cant change variables (globally declared in your class) and you cant change form properties or anything by simply giving them new values within your thread.
When a thread runs, How would you go about changing the text in a label from inside the thread?
I don't think locking the value is necessary since its not used in the main program, so deadlocks wont occur.
What i tried, that failed.
Having a Global variable (int = 0)
Running a test thread to change the variable to 5.
When i want to display that number outside my thread (messagebox.show(int.tostring()) the var is still 0
How would you go about changing things in/on your main form from within a thread?
Code
This code to create a thread i did not use was this.
Thread threadA = new Thread(new ThreadStart(DoWork));
threadA.Start();
When i use that way, i get the error
"Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on"
When i try to edit or change something on my thread.
So i used this code.
the lbldirectory is the name of my partial class.
// StartFileCheckProcess();
workerObject = new lbldirectory();
workerThread = new Thread(workerObject.DoWork);
// the worker thread.
workerThread.Start();
DoWork is my class where i try and change the properties on the Form.
This is the DoWork class. Its really a plain class, but its just to understand the why this happens, and for other people just to understand the reason why and how they can overcome this.
public void DoWork()
{
button1.Text = "Hello there";
}
So that runs the thread, and the thread works, it just cant change anything on my form.
MODIFIED ANSWER (Given by Tudor and Konstantin Vasilcov)
On a button click event.
var t = new Thread(TEST);
t.Start();
The class that the thread starts
private void TEST()
{
for (int i = 0; i < 10; i++)
{
lbl_CurrentFile.BeginInvoke(
((Action)(() => lbl_CurrentFile.Text = i.ToString())));
Thread.Sleep(1000);
}
}
That successfully changes the text of a label inside a thread
Upvotes: 1
Views: 5953
Reputation: 18543
If you need to access GUI from a background thread, you need to use Control.Invoke method:
public void DoWork()
{
button1.Invoke(new Action(() =>
{
button1.Text = "Hello there";
}));
}
If you have some variables shared among several threads, each time a shared variable is accessed by one of the threads must be protected by one of the syncronization techniques explicitly. I guess there you can find a great deal of necessary information: Thread Synchronization (C# Programming Guide)
Upvotes: 6
Reputation: 62439
Ok there are two things to mind here:
1.Changing GUI controls: only the GUI thread should make changes to controls. Other threads need to forward their updates to the GUI thread via Invoke
/BeginInvoke
e.g.:
var t = new Thread(
o =>
{
textBox.BeginInvoke(
((Action)(() => textBox.Text = "text")));
});
2.Changing scalar values or references: this can be normally done with no problems, but be wary of data races.
Upvotes: 7