如何在线程之间传递IUIAutomationElement 我正在用C++编写一个No.js原生插件,与之交互。我试图监听焦点事件,包装导致事件的IUIAutomationElement,并将包装的元素传递给javascript

如何在线程之间传递IUIAutomationElement 我正在用C++编写一个No.js原生插件,与之交互。我试图监听焦点事件,包装导致事件的IUIAutomationElement,并将包装的元素传递给javascript,c++,multithreading,microsoft-ui-automation,node-addon-api,C++,Multithreading,Microsoft Ui Automation,Node Addon Api,我可以附加一个事件侦听器(如下示例),成功接收焦点事件和IUIAutomationElement。但是,所有UIAutomation事件侦听器都在单独的线程中运行 在UI自动化事件处理程序中进行UI自动化调用是安全的,因为事件处理程序总是在非UI线程上调用。 (见:) 例如,这里我将lambda函数传递给IUIAutomation::AddFocusChangedEventHandler方法的包装器 this->automation->SubscribeToFocusChange([callba

我可以附加一个事件侦听器(如下示例),成功接收焦点事件和
IUIAutomationElement
。但是,所有UIAutomation事件侦听器都在单独的线程中运行

在UI自动化事件处理程序中进行UI自动化调用是安全的,因为事件处理程序总是在非UI线程上调用。 (见:)

例如,这里我将lambda函数传递给
IUIAutomation::AddFocusChangedEventHandler
方法的包装器

this->automation->SubscribeToFocusChange([callback,this](IUIAutomationElement*el){
//这里的代码在非主线程中运行
//它得到了正确的IUIAutomationElemenet
}
为了将
IUIAutomationElement
传递回Javascript,我需要将其传递给主线程。
node addon api
提供
Napi::ThreadSafeFunction
,用于在线程之间传递变量

Napi::ThreadSafeFunction callback=Napi::ThreadSafeFunction::New(
环境,
信息[0]。作为(),
“回调”,
0,
1.
);
this->automation->SubscribeToFocusChange([callback,this](IUIAutomationElement*el){
//在非主线程中运行的代码
//艾尔在这里工作
BlockingCall(el[this](Napi::Env Env,Napi::Function jsCallback,IUIAutomationElement*passedEl){
//在主线程中运行的代码
//passedEl应与el相同
}
}
注意:这里的
info[0]
是一个表示Javascript函数的函数参数

问题是,当
el
工作时,任何在
passedEl
上运行的函数都会抛出异常

例如:

BSTR elControlType;
BSTR passedElcontrolType;

// Following works perfectly
HRESULT hr = this->el->get_CurrentLocalizedControlType(&controlType);

// This throws an exception and stops the program
HRESULT hr = this->passedEl->get_CurrentLocalizedControlType(&controlType);
我尝试过的

  • El
    passedEl
    具有相同的内存地址,因此我相信当非主线程停止时,
    IUIAutomationElement
    将失效

  • callback.NonBlockingCall
    与其他变量(
    int
    string
    ,自定义类)完美配合使用

  • 我的问题是,在线程之间传递
    IUIAutomationElement
    的正确方法是什么


    从我所读到的内容来看,我需要阻止Microsoft在非主线程停止时回收该对象。我相信要做到这一点,我需要获取并存储对该对象的引用,但还没有找到任何关于如何进行的文档。

    为了使来自
    IUIAutomation API
    的实例能够跨线程传递,您需要保留一个强引用rence.
    iuiautomationeelement
    基于
    IUnknown
    ,因此可以使用
    IUnknown::AddRef
    ()完成此操作

    这会向引用计数添加一个引用,这意味着一旦创建对象的线程停止并因此停止持有该对象,该对象不会失效

    最终释放对象及其内存也很重要,这可以通过
    IUnknown::release
    ()完成

    这可以通过制作一个像std::shared_ptr这样的包装器来推广,这将有助于管理引用,但是我还没有弄清楚如何做到这一点

    TL;DR:创建
    IUIAutomationElement
    的线程拥有该对象及其内存。为了将其传递给另一个线程,您需要增加引用计数,否则一旦停止,线程将释放该对象/内存