Reputation: 1459
Seems that Oliver is right. After Several tries I got the exception and in debug mode i get it for sure. So this has to be all about timing. You should also check Matthew wattsons answer ;)
First of all a little example that shall explain my confusion.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace testCrossThreading
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
new Thread(ThreadJob).Start();
}
void ThreadJob()
{
//label1.Text = "1";
changeText(label1, "1");
}
void changeText(Label L, String message)
{
L.Text = message;
}
}
}
So now my question: if I uncomment label1.Text = "1";
in the function "ThreadJob" then I get an Cross thread exception as expected.
But if i leave it commented like the example shows it does work. But why?
The function is called by the sub thread and I don't invoke anything. So it is still the sub Thread and not the GUI thread that changes the text of label imo. Or am I missing something?
I would write it like this.
void ThreadJob()
{
Action a = () => label1.Text = "1";
this.Invoke(a);
}
Upvotes: 10
Views: 147
Reputation: 45101
I think it's just a timing issue. If you try to update a gui element from a non-gui thread the cross-thread exception can be thrown. You can even disable the whole cross-thread exceptions by calling
Form.CheckForIllegalCrossThreadCalls = false;
but after the exception is gone, the further behavior is undefined and can lead to very subtle bugs. So take the exception as a hint for a code smell but be aware that sometimes the exception won't be thrown even if it should be.
Upvotes: 7
Reputation: 109567
I think you may have a race condition, which is why results are varying.
If you attempt to change the Text
property of a control which isn't currently displayed, then .Net doesn't care which thread changes it.
In your code, you start a thread from the constructor. The code which actually displays the form may or may not have displayed it before the code in the thread that sets the property executes.
When you call an extra function to set the property, the timings change and exposes the race condition.
You could test this by adding a Thread.Sleep(100)
to the start of ThreadJob()
.
Upvotes: 2