I have such WinForms code:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void bStart_Click(object sender, EventArgs e)
{
Thread thr = new Thread(this.Iterate);
thr.Start(1);
thr = new Thread(this.Iterate);
thr.Start(10000);
thr = new Thread(this.Iterate);
thr.Start(10000000);
}
private void Iterate(object state)
{
int value = (int)state;
while (true)
{
value++;
lbCounter.Text = value.ToString();
Thread.Sleep(10);
}
}
}
It just creates three threads and each of them changes label text.
As I know there is a good rule don't change any WinForms UI from non main thread.
But I was curious why this code works fine when I launch it without attached debugger, and it fails with InvalidOperationException {"Cross-thread operation not valid: Control 'lbCounter' accessed from a thread other than the thread it was created on."}
when I run it with debugger.
I checked source code for Control
class and found such code:
// Initially check for illegal multithreading based on whether the
// debugger is attached.
[ResourceExposure(ResourceScope.Process)]
private static bool checkForIllegalCrossThreadCalls = Debugger.IsAttached;
public IntPtr Handle {
get {
if (checkForIllegalCrossThreadCalls &&
!inCrossThreadSafeCall &&
InvokeRequired) {
throw new InvalidOperationException(SR.GetString(SR.IllegalCrossThreadCall,
Name));
}
if (!IsHandleCreated)
{
CreateHandle();
}
return HandleInternal;
}
}
So based from this code, if I access UI from thread that didn't create that UI, then it will fail when debugger is attached, but it won't do any check and will work without attached debugger.
It seems strange for me, as it may lead to missing cross threaded issues related to UI.
Why it works in such way? As for me it should always do this check either with debugger or without it.