COM组件初始化

用DirectShow到了枚举设备,放在程序开始出,没有任何输出结果,查代码发现用的:

HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &p->pICreateDevEnum);
返回值居然错误,才恍然大悟,原来是没有初始化COM组件。

加上:

CoInitializeEx(NULL,COINIT_MULTITHREADED|COINIT_SPEED_OVER_MEMORY);

一切正常:)

顺便查了下:

CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是 程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
有哪些方式呢?单线程和多线程。
CoInitialize 指明以单线程方式创建。
CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
创 建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。
在使用中,使用CoInitialize创建可使对 象直接与线程连接,得到最高的性能。创建多线程对象可以直接接收所有线程的调用,不必像单线程那样需要消息排队,但却需要COM创建线程间汇集代理,这样 访问效率不高。

注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,一般是在 Dll 中使用 COM 才会需要使用的。





OleInitialize、CoInitialize、CoInitializeEx和AfxOleInit()区别


CoInitialize CoInitializeEx 是用来初始化COM运行环境的。
OleInitialize是初始化Ole的运行环境,Ole是在Com的基础上作的扩展,是ActiveX运行的基础,OleInitialize肯定会调用CoInitialize。

CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
CoInitialize指明以单线程方式创建。
CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
创建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。
CoInitialize并不装载com库,这个函数只是用来初始化当前线程使用什么样的套间。当使用这个函数以后,线程就和一个套间建立了对应关系。
线程的套间模式决定了该线程如何调用com对象,是否需要列集等
套间是com中用来解决并发调用冲突的很有效的办法
Before calling any COM functions, a thread needs to call CoInitialize to load the COM infrastructure (and to enter an apartment). Once a thread calls CoInitialize, the thread is free to call COM APIs.
CoInitializeEx provides the same functionality as CoInitialize and also provides a parameter to explicitly specify the thread's concurrency model. The current implementation of CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread apartment. Applications developed today should call CoInitializeEx rather than CoInitialize.
注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,否则就会有必要在之后每个调用Com的线程中调用CoInitialize来初始化出每个线程自己的套间。

AfxOleInit实际上调用了OleInitialize,虽然它在内部也调用了CoInitializeEx,但它只能处理单线程,这是AfxOleInit和CoInitialize主要区别:
OleInitialize calls CoInitializeEx internally to initialize the COM library on the current apartment. Because OLE operations are not thread-safe, OleInitialize specifies the concurrency model as single-thread apartment.
Once the concurrency model for an apartment is set, it cannot be changed. A call to OleInitialize on an apartment that was previously initialized as multithreaded will fail and return RPC_E_CHANGED_MODE.

应用:
1. CoInitialize 仅仅初始化Com,支持多线程。也就是说如果多线程调用Com接口,必须在每个线程中都调用CoInitialize。
2. OleInitialize 初始化Com(其实也是调用CoInitializeEx),支持多线程。比CoInitialize多了一下内容:
A) Clipboard
B) Drag and drop
C) Object linking and embedding (OLE)
D) In-place activation
如果不需要这些,用CoInitialize就可以。
3. AfxOleInit是MFC对OleInitialize的封装。貌似不支持多线程,也就是说只能在主进程调用该函数,如果线程需要使用Com必须调用上面的两个来实现初始化。而且MSDN明确标明AfxOleInit不能在MFC的DLL中调用,否则也会造成初始化失败。
4.OleInitialize和OleUninitialize( )成对使用;CoInitialize和CoUninitialize成对使用;CoInitializeEx和CoUninitialize成对使用;AfxOleInit()由MFC自动释放。

VC++使用ADO访问ACCESS时,出现_RecordsetPtr Open卡或者_ConnectionPtr Excute卡或者_CommandPtr Excute一直卡住等莫名其妙的情况时,而语法又没有错误时,请确定初始化COM函数。
MFC程序建议使用AfxOleInit()。
在 Android 开发中,**Initializer** 通常指的是 `androidx.startup` 库中的 **`AppStartup`(或称 Jetpack Startup)**,它提供了一种统一的方式来初始化应用中的组件(如 SDK、库等),并且支持设置初始化顺序。 --- ### 🔧 什么是 `androidx.startup`? `androidx.startup` 是 Jetpack 提供的一个库,用于通过 ContentProvider 实现 **自动化的应用组件初始化**。它替代了过去在 `Application.onCreate()` 中手动调用各种 `SDK.init()` 的方式。 --- ## ✅ 如何使用 Initializer 设置初始化顺序? 虽然 `androidx.startup` 默认是并行初始化的,但它 **支持依赖关系定义**,即你可以通过声明依赖来控制初始化顺序。 ### 步骤 1:添加依赖 ```gradle implementation "androidx.startup:startup-runtime:1.1.1" ``` ### 步骤 2:创建自定义 Initializer 假设你有两个组件: - `DatabaseInitializer`:负责数据库初始化 - `AnalyticsInitializer`:依赖数据库,必须在其之后初始化 #### 示例代码: ```java // DatabaseInitializer.java public class DatabaseInitializer implements Initializer<Void> { @Override public Void create(Context context) { // 模拟数据库初始化 MyDatabase.getInstance(context); Log.d("Init", "Database initialized"); return null; } @NonNull @Override public List<Class<? extends Initializer<?>>> dependencies() { // 这个组件没有前置依赖 return Collections.emptyList(); } } ``` ```java // AnalyticsInitializer.java public class AnalyticsInitializer implements Initializer<Void> { @Override public Void create(Context context) { // 初始化分析 SDK,依赖数据库已准备好 AnalyticsSdk.init(context); Log.d("Init", "Analytics initialized"); return null; } @NonNull @Override public List<Class<? extends Initializer<?>>> dependencies() { // 必须等待 DatabaseInitializer 完成 return Arrays.asList(DatabaseInitializer.class); } } ``` ### 步骤 3:在 `AndroidManifest.xml` 中声明(可选) 如果你希望某个 Initializer 自动初始化,需要在 `AndroidManifest.xml` 的 `<provider>` 中注册: ```xml <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- 声明需要自动初始化组件 --> <meta-data android:name="com.example.DatabaseInitializer" android:value="androidx.startup" /> <meta-data android:name="com.example.AnalyticsInitializer" android:value="androidx.startup" /> </provider> ``` > 注意:只有你想让它“自动启动”才需要注册。否则可以在代码中手动调用。 --- ### ✅ 初始化顺序是如何保证的? - `dependencies()` 方法返回一个 `List<Class<Initializer>>` - Startup 库会根据依赖关系构建一个 **有向无环图(DAG)** - 然后按拓扑排序执行初始化,确保依赖项先于被依赖项执行 例如: ``` DatabaseInitializer → AnalyticsInitializer ``` 因为 `AnalyticsInitializer.dependencies()` 包含 `DatabaseInitializer.class`,所以前者会先执行。 --- ### ✅ 手动触发初始化(可选) 你也可以不自动初始化,而在 `Application` 中手动控制: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); // 手动触发初始化(会自动处理依赖顺序) long startTime = System.currentTimeMillis(); Startup.getInstance().initializeComponent(this, AnalyticsInitializer.class); Log.d("Init", "Total init time: " + (System.currentTimeMillis() - startTime) + "ms"); } } ``` 这将自动触发 `DatabaseInitializer` 先执行,再执行 `AnalyticsInitializer`。 --- ### ❗ 注意事项 | 要点 | 说明 | |------|------| | ⚠️ 不要循环依赖 | `A → B → A` 会导致异常 | | ✅ 支持多线程 | 非依赖任务可以并发执行 | | 📦 自动合并多个模块的初始化 | 适合 SDK 开发者使用 | | 🔒 初始化发生在主线程? | 默认部分在后台线程,但 `ContentProvider.attachInfo` 在主线程 | --- ### 💡 使用场景 - 多个第三方 SDK 初始化(如 Firebase、友盟、Bugly) - 数据库、缓存、网络层等基础组件依赖管理 - 组件化架构中跨模块初始化顺序控制 --- ### ✅ 最佳实践建议 1. 将每个模块封装成一个 `Initializer` 2. 明确写出 `dependencies()` 来控制顺序 3. 对性能敏感的任务考虑是否放异步 4. 使用日志或性能监控跟踪各组件初始化耗时 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值