为啥我的 IUnknown 释放函数会阻塞我的子线程?
Posted
技术标签:
【中文标题】为啥我的 IUnknown 释放函数会阻塞我的子线程?【英文标题】:why my IUnknown release function block my child thread?为什么我的 IUnknown 释放函数会阻塞我的子线程? 【发布时间】:2021-04-17 12:48:06 【问题描述】:在我的 C 应用程序中,我有一个子线程在他生命的开始时检索一个 IUnknown 接口:
static struct IUnknown* punk = NULL;
void DispatcherStart()
CoInitialize(NULL);
CheckHRESULT(GetActiveObject(&MY_CLSID,NULL,&punk));
一切都很好,它被用来调用一些activeX函数并且它工作!但是,当我的程序结束时,它要求线程终止,所以我的线程调用正在结束函数:
void DispatcherStop()
if(punk) (punk)->lpVtbl->Release(punk); // BLOCK here
punk = NULL;
CoUninitialize();
我的thead 永远不会返回,因为我的 IUnknow ptr 上的 Release 会阻止它。 (如果我删除 Release 那么 COUnitialize() 块)
我做错了什么? (不能在主线程中进行朋克初始化)
【问题讨论】:
没有太多信息可以继续。我的经验是 GetActiveObject() 通常被称为进程外对象。在进程外对象的情况下,我认为您的 Release() 将被阻止直到超时......可能是 30 秒。超时后,它将返回。我确实注意到 GetActiveObject() 是在 oleauto.h 中声明的。一般来说,CoInitialize() 和 OleInitialize() 之间没有太大区别,但可能有一些区别。我可能会尝试使用 OLE 函数 OleInitialize(NULL) 和 OleUnitiaize() 而不是“Co”版本。 @JosephWillcoxson 感谢您的帮助,Ole 和 Co 版本没有区别。两者都阻止我的线程,我必须设置超时才能正确关闭我的应用程序。 @JosephWillcoxson 确实没有太多信息。我的代码目前非常简单。我的线程通过 oleInit / CoInit 然后直接初始化 OLE。为了提供更多上下文,我正在编写一个基本代码,它初始化一个 ActiveX 服务器,然后启动连接到这个 ActiveX 服务器的我的子线程。到最后,我的线程在释放activeX服务器之前释放。 如果我尝试从主线程初始化我的 IUnknown ptr,那么一些 activeX 函数什么也不做(所有在 GUI 上工作的 activeX 函数)和一些工作。发布和 OleUninit 工作并且不会阻塞 OleUnitialize 是某些操作所必需的,例如剪贴板、拖放等。在您的情况下似乎不需要。像您这样的 STA 线程(由 CoInitialize 盯着)必须泵送消息循环 docs.microsoft.com/en-us/windows/win32/com/… 。您的 Release 调用会向不(似乎)发送消息的消息循环发送消息。 【参考方案1】:如果没有消息泵,执行CoInitialize
的线程将失败。因此,如果线程没有自己的线程,请使用CoInitializeEx(NULL,COINIT_MULTITHREADED);
。
但后一种情况仅适用于 mta com。
这并不意味着您只需将CoInitialize
更改为CoInitializeEx..
mta com 应该有自己的基地。你应该提供它。就像我在那里做的那样https://github.com/alexeyneu/tool3/blob/00bfd2aaf2973626f166ea754b756fd0f2fa0d0b/tool3/MainFrm.cpp#L254
【讨论】:
以上是关于为啥我的 IUnknown 释放函数会阻塞我的子线程?的主要内容,如果未能解决你的问题,请参考以下文章
为啥当我的子查询无效时,此 SQL 查询会起作用? - 甲骨文 [重复]