- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
考虑编写一个可重用的自定义函数,在其函数体内创建 COM 对象并调用某些 COM 接口(interface)的方法。为了使其正常工作,必须调用 CoInitializeEx
和匹配的 CoUninitialize
API。
在函数体内部调用那些 COM 初始化和清理 API 会向调用者隐藏 COM 实现细节,同时也会减轻调用者的负担。
但是在函数体内调用 CoInitializeEx
和匹配的 CoUninitialize
是否被认为是一种好的编码习惯?
在函数粒度级别调用那些 COM 初始化/清理函数是否意味着每个函数调用的开销太大?
这种设计还有其他缺点吗?
最佳答案
这是一种糟糕的做法,而且根本上是错误的。重要的是第二个参数 (dwCoInit) 的值。它必须是 COINIT_APARTMENTTHREADED,通常缩写为 STA,或 COINIT_MULTITHREADED (MTA)。这是你做出的 promise ,誓死不渝的风格。如果你违背了 promise ,那么程序就会死掉。通常是由于死锁、未获得预期事件或性能慢得令人无法接受。
当您选择 STA 时,您就可以保证该线程运行良好并且可以支持非线程安全的 COM 组件。实现这个 promise 需要线程泵出一个消息循环并且从不阻塞。例如,支持 GUI 的线程的常见行为。绝大多数 COM 组件都不是线程安全的。
当您选择 MTA 时,您根本就没有 promise 任何支持。该组件现在必须自生自灭以保持自身线程安全。通常通过让 COM 基础结构自己创建一个线程来为组件提供一个安全的家来自动完成。您需要注意的进一步细节是编码(marshal)接口(interface)指针,需要 CoMarshalInterThreadInterfaceInStream() 辅助函数或更方便的 IGlobalInterfaceTable 接口(interface)。这确保创建一个代理来处理所需的线程上下文切换。
MTA 听起来很方便,但并非没有后果,一个简单的属性 getter 调用可能会花费多达 x10000 倍的时间。线程上下文切换带来的开销以及跨堆栈帧复制任何参数和返回值的需要。编码(marshal)接口(interface)指针很容易失败,COM 组件的作者通常不提供必要的代理/ stub ,或者他们故意省略它,因为复制数据太困难或太昂贵。
关键是图书馆永远无法在 STA 和 MTA 之间做出选择。它不知道关于线程的 beans,它没有创建那个线程。并且不可能知道线程是否泵出消息循环或 block 。这些代码完全超出了图书馆的范围。否则 COM 基础结构也需要知道这一点的确切原因,它同样无法对线程做出假设。
选择必须由创建和初始化线程的代码做出,通常是应用程序本身。除非库为了使调用安全而创建线程。但是随之而来的结果是代码总是很慢。您通过返回不可避免的 CO_E_NOTINITIALIZED 错误代码来提醒库的调用者他没有正确处理。
Fwiw,这是您在 .NET Framework 中看到的东西。 CLR 总是在线程可以执行任何托管代码之前调用 CoInitializeEx()。仍然是应用程序的程序员必须做出的选择,或者更典型的是项目模板,通过 Main() 上的 [STAThread] 属性或工作线程的 Thread.SetApartmentState() 调用来完成。
关于c++ - COM 初始化和清理是否适合函数级粒度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40936774/
我有 2 个事实表,每个表都有一个度量组,生产和生产订单。生产具有较低粒度的生产信息(在组件级别)生产订单具有较高级别的信息(具有抬头数量等的订单级别)。 我在 productionorderid 的
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我第一次尝试了解 Akka/Actors,并且对每个 Actor 职责的粒度有点困惑。 在我的应用程序中,有可以使用 WidgetRegistrar 注册/取消注册的 Widget。要向 Regist
我们一直在使用 MVP 模式和 Winforms,并取得了相当大的成功。然而,关于 MVP 总是弹出一个问题: 对于演示者来说,什么是好的粒度? 我的意思是:对于 Winforms,细粒度通常适用于用
我通常使用 git add -p 添加更改,而且很多时候有几个代码块的大块头,由空行分隔。 但是,git 不会进一步拆分 大块头,我不得不求助于手动编辑。 如何增加 hunk 的粒度,以便每个代码块都
例如,我看到 dumps.wikimedia.org/other/pagecounts-raw/,但那里没有特定国家/地区的数据... 最佳答案 据我所知,没有。出于明显的隐私原因,发布的页面查看统计
JavaScript 的源映射似乎通常不比 token 粒度更精细。 例如,identity-map uses token granularity . 我知道我看过其他例子,但不记得在哪里。 为什么我
我有这些目录: ./Tools ./ook/Tools. 我在 setup.cfg 中的 py.test 的 norecursedirs 选项中添加了 Tools。正如预期的那样,当 py.test
我正在使用这个 Accelerometer graph来自 Apple 并尝试转换他们的 G-force 代码以计算 +/- 128。 下图显示标签中的 x、y、z 值与图表上的输出不匹配:(请注意,
此问题围绕 Android 应用程序的架构展开。 在使用 LifeCycle 组件 ViewModel 时,最好是每个 fragment 一个 ViewModel 还是订阅 fragment 的父 A
我是一名优秀的程序员,十分优秀!