我在 google/here 上看到了很多关于从另一个线程更新 UI 元素的线程。
如果我只想获取复选框的值怎么办?
我能做到这一点而不必做任何特别的事情吗?
我在 google/here 上看到了很多关于从另一个线程更新 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 的实验表明它可以在Text
不使用Invoke/BeginInvoke
. 有趣的是,似乎设置属性也可以正常工作(没有调用),尽管我敢打赌它不是线程安全的,并且应用程序不会出于某种原因抱怨。
底线:在任何情况下,在与来自其他线程的 GUI 组件交互时使用调度程序都是一个好主意,因为它确保读/写被序列化到单个线程,因此您没有线程安全问题。
您可以从另一个线程访问 UI 元素吗?(不设置)?
不。
这是交易。UI 元素有非常严格的线程亲和性要求。这意味着您只能从托管它的线程访问该元素。这包括各种访问,包括简单读取。1
它对于简单的属性获取器可能工作得很好,但其感知的安全性将是特定控制实施方式的意外结果。由于Control
实例具有线程亲和性,它们可能会使用线程本地存储技术来保存它们的一些状态,当然,这些状态与不同的线程不兼容。或者,如果您尝试读取的值处于半生不熟的状态怎么办?由于写入可能发生在您无法控制的代码中,因此无法同步对该读取的访问。这仍然忽略了可能出现的微妙的内存屏障问题。
同样,如果它看起来有效,那么将其归为意外。从线程访问 UI 元素而不是从线程访问它们是灾难的根源。事情可能会出人意料地失败。
1这条规则很少有例外。使用这些ISynchronizeInvoke
方法就是这样的一个例外。
你可以但严格来说它不是线程安全的。例如,如果属性 Get 代码包含多个操作,则 UI 线程可能会在 Get 操作的中途同时进行操作,从而导致意外结果。
只需像往常一样读取值。仅要更新控件,您需要切换到 GUI 线程。