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);
}
The issue of cross threading occurs most commonly when a screw is installed at a slight angle, causing the threads of the screw to not match up correctly with those of the nut or threaded hole. This can result in the fastening jamming or becoming damaged.
What is cross-threading? Cross-threading occurs when the first external thread crosses the internal thread in such a way that the thread contacted on one side of the internal thread is not on the same revolution as the thread contacted on the opposite side.
A cross-threaded screw occurs when the threads of a screw do not properly align with the threads in the part being fastened. Cross-threading is typically caused when the two parts being fastened together aren't properly aligned, so the holes don't match up.
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.
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()
.
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