很可能一般情况下,我的问题无法得到解答,如果是这样,那么这个有趣的信息无论如何都是如此。我试图更好地理解UI控件交互,特别是非UI线程允许执行的内容和内容。在我的情况下,我与WPF控件和Microsoft.Office.Interop命名空间中的对象(代表控件)进行交互。我在模型层中对后台线程做了很多工作,但是当我在视图模型中收到事件时,我在UI线程上调度(这通常在使用绑定的属性时)到WPF控件)。这对我来说很有意义,似乎运作良好。但是,我不确定背景线程可以做什么和不能做什么。从本质上讲,我试图了解边界的位置。为了获得想象力,请参阅下面的一些问题。我理解我的请求有点开放,所以如果有人知道外部资源,我可以读到这对我来说同样好。
get()
绑定到后台线程的ui属性,即只有set()
必须从UI线程完成吗?总之,在后台线程和UI线程之间切换时,我能记住一条好的规则吗?例如" 更改 ui控件的任何操作必须在ui线程"或" 直接交互的任何操作上完成,无论如何使用ui控件的操作(例如检查get()
)必须在ui线程上完成"。
答案 0 :(得分:2)
任何都不是线程安全的,试图偷工减料会让你遇到麻烦。你可能认为财产获取者是无辜的,但事实并非如此。当用户在线程运行时继续与UI交互时,没有任何事情发生,您将从过时值计算结果并呈现与UI状态不一致的结果。您知道如果不改变对线程的作用至关重要的值,那么您的用户就不会。
没有锁定可以解决这个问题,你无法在UI线程中设置锁定,也无法锁定用户。除了明显的一个,你需要编写代码,防止用户在线程滚动时更改值。现在这使得获取线程内部的值变得非常不必要,您可以在启动线程之前获取它。将lambda表达式传递给线程代码非常方便。
您当然可以允许用户更改UI,但您必须编写更复杂的线程代码。您必须确保当前线程停止并启动一个新线程,现在使用更新的值。很难做到正确,线程停止不是瞬间的,容易死锁。
同样适用于线程的结果,更新线程内的UI通常没有意义。 BackgroundWorker和Task类可帮助您在完成线程后在UI线程上启动代码,它可以安全地使用结果更新UI。让线程做一些容易思考并且易于互锁的小东西对于避免麻烦非常重要。
Office互操作与WPF略有不同,COM中的线程安全是自动的。它自动调用Dispatcher.Invoke()的等价物,不需要额外的帮助。在工作线程运行时,Office文档更可能保持静态。除非您允许用户也更改文档,否则您会在黑桃中遇到吸气剂问题。 YMMV。