你可以从另一个线程访问UI元素吗? (没有设定)

我在google / here上看到很multithreading在UPDATING来自另一个线程的UI元素。

如果我想获得复选框的值,该怎么办?

我能不做任何特别的事情吗?

编辑 :我似乎必须收回我之前写的内容。 试过以下内容:

添加了一个名为myTextBox的文本框,并尝试检索Text属性的值:

 Thread t = new Thread( o => { Thread.Sleep(2000); string value = myTextBox.Text; Thread.Sleep(2000); }); t.Start(); 

似乎应用程序(WPF)在2秒后崩溃。 使用调度程序工作:

 Thread t = new Thread( o => { Thread.Sleep(2000); myTextBox.Dispatcher.BeginInvoke( (Action)(() => { string value = myTextBox.Text; })); Thread.Sleep(2000); }); t.Start(); 

因此,在从GUI组件读取值时,您仍需要通过调度程序线程,至少在WPF中。

第二次编辑 :这会变得更好。 显然重复经典WinForms的实验表明,它可以在不使用Invoke/BeginInvoke情况下读取Text属性。 有趣的是,似乎也设置属性工作正常(没有调用),虽然我打赌它不是线程安全的,应用程序不会因为某些原因抱怨。

结论 :在任何情况下,在与来自其他线程的GUI组件交互时使用调度程序是个好主意,因为它确保将读/写序列化为单个线程,因此您没有线程安全问题。

你可以从另一个线程访问UI元素吗? (没设定)?

没有。

这是交易。 UI元素具有非常严格的线程亲和力要求。 这意味着您只能从托管它的线程访问该元素。 这包括各种访问,包括简单的读取。 1

它对于简单的属性获取者可能工作正常,但其感知的安全性将是特定控制实现方式的偶然结果。 由于Control实例具有线程关联性,因此它们可能使用线程本地存储技术来保存它们的某些状态,当然这些状态与不同的线程不兼容。 或者,如果您尝试阅读的值处于半生不熟状态,该怎么办? 由于写入可能发生在您无法控制的代码中,因此无法同步对该读取的访问。 而且这仍然忽略了可能出现的微妙的记忆障碍问题。

再说一次,如果看起来有效,那就把它当成一个意外。 从托管它们的线程访问UI元素是灾难的一个方法。 事情可能无法预测和惊人地失败。


1 这条规则很少有例外。 使用ISynchronizeInvoke方法就是一个这样的例外。

你可以但严格来说它不是线程安全的。 例如,如果属性Get代码包含多个操作,则UI线程可以在Get操作期间的中途行动,从而导致意外结果。

只需像平常一样读取值即可。 只有更新控件,才需要切换到GUI线程。