我正在编写一个C ++ DLL,它从Excel VBA传入SAFEARRAY。 DLL有多个线程共享SAFEARRAY(读取和写入它们)。在试图找出如何安全地进行共享时,我遇到了this bit of MSDN documentation:
例如,考虑使用SafeArrayLock和SafeArrayUnlock函数的应用程序。如果从同一SAFEARRAY数据类型实例上的不同线程同时调用这些函数,则可能会创建不一致的锁定计数。这最终将导致SafeArrayUnlock函数返回E_UNEXPECTED。您可以通过提供自己的同步代码来防止这种情况。
令我困惑的是因为我认为锁的全部意义在于确保线程的安全性,并且显然这种锁定功能并不适用于此。但是为什么需要锁定单线程应用程序呢?
SafeArrayLock的文档还说该函数“在数组描述符的pvData中放置一个指向数组数据的指针”,但是通过我的测试,即使从未调用过SafeArrayLock,pvData指针仍然有效(并且锁定计数是0)。例如,这个函数:
void __declspec(dllexport) __stdcall testfun(VARIANT& vararr) {
if (vararr.parray->cLocks != 0) throw -1;
else {
double* data = (double*) vararr.parray->pvData;
data[5] = 4.1;
}
}
有效地写入存储在vararr中的数组,并且在调用它的VBA中可以看到更改。怎么了?
鉴于pvData和不安全的锁定机制看似持久,我的本能就是废弃所有数组操作函数,让我的线程随心所欲地进入pvData(写入永远不会发生碰撞,所以可能会出错?)但是由于原因不明,其他人在此谨慎对抗手动阵列操作。什么是正确的方法?提前谢谢。