UI线程vs后台线程- UI控件可访问性边界

本文关键字:UI 线程 访问 边界 vs 后台 控件 | 更新日期: 2023-09-27 18:02:05

很可能我的问题一般无法回答,如果是这样,那也是有趣的信息。我试图更好地理解UI控制交互,特别是什么是和什么是不允许由非UI线程执行。在我的例子中,我既与WPF控件交互,也与位于Microsoft.Office.Interop名称空间中的对象(表示控件)交互。我在模型层的后台线程上做了很多工作,但是当我的视图模型中接收到事件时,我正在UI线程上调度(这通常是在处理绑定到WPF控件的属性时)。这对我来说很有意义,而且似乎很有效。我不确定,但是,关于什么可以和不能做后台线程。从本质上讲,我试图理解边界在哪里。为了激发想象力,请看下面的一些问题。我知道我的请求有点开放,所以如果有人知道我可以阅读的外部资源,那对我来说也一样好。

  • 我可以从后台线程绑定到ui的属性上get(),即只有set()必须从ui线程完成吗?
  • 如果我有一个互操作对象,比如Microsoft.Office.Interop。幻灯片,在我看来,我必须在UI线程上与它交互因为它是一个实际的UI控件。但是我可以在非ui线程中监听返回这些对象的事件吗?我可以从非ui线程检查幻灯片为null吗?我可以get()的属性包含在幻灯片类型从一个非ui线程?

总之,在后台线程和UI线程之间切换时,是否有一个好的规则我可以记住?例如"任何改变 ui控件的动作必须在ui线程上完成",或者"任何直接与交互的动作,无论动作(例如检查null)与ui控件必须在ui线程上完成"。

UI线程vs后台线程- UI控件可访问性边界

任何与UI交互的都不是线程安全的,试图偷工减料会给你带来麻烦。你可能认为属性getter是无害的,但事实并非如此。当线程运行时,用户继续与UI交互时,不会发生什么漂亮的事情,您将根据过时的值计算结果,并呈现与UI状态不一致的结果。你会知道不要改变一个值,这个值对线程的工作很重要,你的用户不会。

没有锁可以解决这个问题,你不能把锁放在UI线程中,你不能把锁放在用户上。除了最明显的一个之外,您需要编写代码来防止用户在线程处理时更改值。这样就不需要在线程内部获取该值了,您可以在启动线程之前获取该值。将lambda表达式传递给线程代码非常方便。

你当然可以允许用户改变UI,但是你必须编写更复杂的线程代码。您必须确保当前线程停止并启动一个新线程,现在使用更新后的值。很难做到正确,线程停止不是瞬间的,容易死锁。

同样适用于线程的结果,通常没有必要在线程内部更新UI。BackgroundWorker和Task类帮助你在UI线程上启动代码,在线程完成后,它可以安全地用结果更新UI。让线程做一些容易思考和容易联锁的小事对于避免麻烦是非常重要的。

Office互操作与WPF有点不同,线程安全在COM中是自动的。它会自动调用Dispatcher.Invoke()的等价函数,不需要额外的帮助。在工作线程运行时,Office文档更有可能保持静态。除非允许用户也更改文档,否则getter问题就会再次出现。YMMV .