我有这样的WinForms代码:
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);
}
}
}
它只创建三个线程,每个线程都会更改标签文本。
据我所知,有一个很好的规则是不要从非主线程更改任何WinForms UI。
但我很好奇为什么这个代码在我没有附加调试器的情况下启动它时工作正常,并且当我用调试器运行它时失败了InvalidOperationException {"Cross-thread operation not valid: Control 'lbCounter' accessed from a thread other than the thread it was created on."}
。
我检查了Control
类的源代码并找到了这样的代码:
// 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;
}
}
因此,基于此代码,如果我从没有创建该UI的线程访问UI,那么在附加调试器时它将失败,但它不会进行任何检查,并且无需附加调试器就可以工作。
对我来说这似乎很奇怪,因为它可能会导致缺少与UI相关的交叉线程问题。
为什么它以这种方式运作?至于我,它应该总是使用调试器或不使用它来检查。