表单,控件和线程

时间:2015-08-10 16:58:16

标签: .net multithreading winforms controls

因此,我将一个方法移动到后台工作程序的DoWork事件中,以便在访问远程资源时不会终止UI。我完全清楚我正在这样做,因为该方法访问表单上的一些控件而不是线程友好的事情,因此需要进行一些重构。令我惊讶的是,不,它运行得很好。奇怪,但我没有质疑,虽然它仍然在我脑海中嘎嘎作响。奇怪。

然后我添加了另一个控件,一个用于时区选择的ComboBox。我将该行添加到DoWork方法以访问该值并且BAM ...交叉线程操作无效。

 private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
 {
     backgroundWorker1.ReportProgress(0, new Status("Initializing...", StatusState.Initializing));

     Query query = new Query();
     query.Hostname = textBoxHostname.Text;                         // Valid...
     query.Port = Int32.Parse(textBoxPort.Text);                    // Valid...
     query.Point = Int32.Parse(textBoxPoint.Text);                  // Valid...
     query.Start = dateTimePickerStart.Value;                       // Valid...
     query.End = dateTimePickerEnd.Value;                           // Valid...
     query.Sampling = Sampling.Parse(textBoxSampling.Text);         // Valid...
     query.Timezone = (TimeZoneInfo)comboBoxTimezone.SelectedValue; // Not Valid!

     // Run query
}

那么为什么在另一个线程上创建的控件的所有其他调用都很好,但是这个调用会爆炸吗?我的猜测是.NET方面的某种缓存,以便其他人永远不会实际访问底层控件。如果没有回复,可能需要尽快深入了解一些参考资料。

我想我应该补充说,我已经通过简单地构建Query对象并将其传递给BackgroundWorker.RunWorkerAsync()调用来修复错误。我真的在寻找解释而不是解决方案。

1 个答案:

答案 0 :(得分:0)

  

我真的在寻找和解释

微软在这方面简直不一致。你知道你不应该从另一个线程访问TextBox,但无论如何。某些控件允许您从其他线程读取其值,而其他控件则不允许。无论如何,你不应该首先做到这一点。 ;)

作为将所有内容传递到RunWorkerAsync()的替代方法,您可以执行以下操作:

 Query query = new Query();
 this.Invoke((MethodInvoker)delegate {
     query.Hostname = textBoxHostname.Text;                         // Valid...
     query.Port = Int32.Parse(textBoxPort.Text);                    // Valid...
     query.Point = Int32.Parse(textBoxPoint.Text);                  // Valid...
     query.Start = dateTimePickerStart.Value;                       // Valid...
     query.End = dateTimePickerEnd.Value;                           // Valid...
     query.Sampling = Sampling.Parse(textBoxSampling.Text);         // Valid...
     query.Timezone = (TimeZoneInfo)comboBoxTimezone.SelectedValue; // Not Valid!
 });