了解线程问题

本主题介绍 Microsoft UI 自动化 客户端实现的常见线程处理方案,并说明如何避免在客户端错误使用线程时可能出现的问题。

本主题包含以下各节:

UI 自动化和 UI 线程

由于UI 自动化使用 Windows 消息的方式,当客户端应用程序尝试在 UI 线程上与其自己的 UI 交互时,可能会发生冲突。 这些冲突可能会导致性能非常缓慢,甚至导致应用程序停止响应。

如果客户端应用程序旨在与桌面上的所有元素(包括其自己的 UI)交互,则应从单独的线程发出所有UI 自动化调用。 这包括查找元素,例如,通过使用 IUIAutomationTreeWalkerIUIAutomationElement::FindAll 方法以及使用控件模式。 此线程不应拥有任何窗口,并且应该是组件对象模型 (COM) 多线程单元 (MTA) 模型线程, (一个使用 COINIT_MULTITHREADED 标志调用 CoInitializeEx 初始化 COM 的模型线程。)

在UI 自动化事件处理程序中进行UI 自动化调用是安全的,因为事件处理程序始终在非 UI 线程上调用。 但是,当订阅可能源自客户端应用程序 UI 的事件时,必须在非 UI 线程上调用 IUIAutomation::AddAutomationEventHandler 或相关方法, (这也应该是 MTA 线程) 。 删除同一线程上的事件处理程序。

UI 自动化客户端不应使用多个线程来添加或删除事件处理程序。 如果在同一客户端进程中添加或删除另一个事件处理程序时添加或删除另一个事件处理程序,则可能会导致意外行为。

事件处理程序的线程模型

UI 自动化客户端应将 COM MTA 线程模型用于实现事件处理程序的线程。 使用单线程单元 (STA) 模型可能会导致问题,例如阻止客户端从线程中删除事件处理程序。

64 位 Windows 上的 COM 单元相关性

根据 COM 规范,远程对象的生存期受单元的生存期控制,在其中调用 CoCreateInstance 函数来创建对象。 当原始单元关闭时,也会释放远程对象。

对于UI 自动化客户端,此 COM 行为可能意味着由 32 位元素使用的UIAutomationCore.dll) 创建的远程 32/64 帮助程序 (的生存期受创建该元素的线程的单元生存期控制。 如果UI 自动化客户端将元素封送到另一个线程,则当原始单元关闭时,该元素可能会失效。 UI 自动化客户端应通过使用封送的自动化元素时捕获错误来正常处理这些问题。

具有 64 位元素的 32 位UI 自动化客户端可能会出现相同的问题。

概念性

获取 UI 自动化元素

订阅UI 自动化事件

UI 自动化事件概述

其他资源

信息:OLE 线程模型的说明和工作