我在 x64 应用程序中使用了 Microsoft Access Database Engine 2010 (Microsoft Office 2016 的一部分)用于处理 mdb 文件。
但是,当前版本的 Microsoft Access Database Engine 2010(OLEDB 提供程序 Microsoft.ACE.OLEDB.12.0)有一个错误。
该引擎在多线程工作中崩溃。
如果我在不同的线程中与此提供程序创建两个 OLE DB(或 ADO DB)连接,那么其中一个将在 Mso40UIwin32client.dll
中崩溃。异常 0xC0000005: Access 冲突写入位置 0x0000000000000000。
异常堆栈:
C++ 异常:std::runtime_error 在内存位置
0x0000006B771FEAF0。
ACEOLEDBTest.exe:Microsoft C++ 异常:内存中的 [rethrow]
位置 0x0000000000000000。
在 ACEOLEDBTest.exe 中:Microsoft C++ 异常:std::runtime_error at
内存位置 0x0000006B771FEAF0。
ACEOLEDBTest.exe 中的 0x00007FFB32361F28:Microsoft C++ 异常:
内存位置 0x0000006B771FEFB8 处的 std::runtime_error。
在 0x00007FFAF9ED1271 (Mso40UIwin32client.dll) 中抛出
ACEOLEDBTest.exe:0xC0000005: Access 冲突写入位置
0x0000000000000000。
带有此错误的 C++ 代码示例:
#include "stdafx.h"
#include <atlcom.h>
#include <atldbcli.h>
#include <conio.h>
typedef UINT(__stdcall* fnThread)(PVOID);
HANDLE hExitEvent = NULL;
UINT __stdcall DbThread1(IN PVOID context)
{
HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hRes));
CDataSource DataSource; // Data source connection object
while (::WaitForSingleObject(hExitEvent, 0) != WAIT_OBJECT_0)
{
// Open DB connection
ATLTRACE2(atlTraceGeneral, 0, L"DbThread1: Create connection...\n");
hRes = DataSource.OpenFromInitializationString(L"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=\"C:\\Temp\\Index_empty1.mdb\"; Persist Security Info=False;");
_ASSERTE(SUCCEEDED(hRes));
// Close DB connection
DataSource.Close();
ATLTRACE2(atlTraceGeneral, 0, L"DbThread1: Close connection...\n");
Sleep(20);
}
::CoUninitialize();
_endthreadex(0);
return 0;
}
UINT __stdcall DbThread2(IN PVOID context)
{
HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hRes));
CDataSource DataSource; // Data source connection object
while (::WaitForSingleObject(hExitEvent, 0) != WAIT_OBJECT_0)
{
// Open DB connection
ATLTRACE2(atlTraceGeneral, 0, L"DbThread2: Create connection...\n");
hRes = DataSource.OpenFromInitializationString(L"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=\"C:\\Temp\\Index_empty2.mdb\"; Persist Security Info=False;");
_ASSERTE(SUCCEEDED(hRes));
// Close DB connection
DataSource.Close();
ATLTRACE2(atlTraceGeneral, 0, L"DbThread2: Close connection...\n");
Sleep(20);
}
::CoUninitialize();
_endthreadex(0);
return 0;
}
int main()
{
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
hExitEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
const fnThread aPtrs[] = { DbThread1, DbThread2 };
HANDLE hDbThread[_countof(aPtrs)] = { NULL };
for (int nIndex = 0; nIndex < _countof(aPtrs); nIndex++) {
if ((hDbThread[nIndex] = (HANDLE)::_beginthreadex(nullptr, 0, aPtrs[nIndex], nullptr, 0, nullptr)) == NULL)
{
return 1;
}
}
CComVariant varData;
printf("Press any key to exit...");
// Loop until any key struck
while (!_kbhit())
{
for (DWORD i = 0; i < 100; i++)
{
// Test for bug of the OLEDB provider for MS ACCESS 2010.
varData.Clear();
}
Sleep(0);
}
// Request threads to exit
SetEvent(hExitEvent);
// Wait for threads to exit
WaitForMultipleObjects(_countof(hDbThread), hDbThread, TRUE, INFINITE);
for (auto& h : hDbThread) {
CloseHandle(h);
}
CloseHandle(hExitEvent);
::CoUninitialize();
return 0;
}
您应该使用 Visual C++ 2013/2015 为 x64 平台构建此示例。
我在 MS forum 发现的类似错误.有谁能够帮助我?
最佳答案
我们在多线程 VB.Net (Framework v4.5.2) 服务应用程序中也遇到过这个问题。经过多次测试,我们发现解决此问题的唯一方法是使用单个线程或关闭连接池(使用 OLE DB Services=-2)。最后我们选择了后者,因为我们需要系统能够并行处理请求。
仅供引用,我安装的 Office 2016 版本不包含此驱动程序(因此我们的程序通过了任何类型的基本测试),但它包含在我们客户安装的 Office 2016 版本中。到目前为止,我已经检查了“Microsoft Office Professional Plus 2016”(来自 MSDN 和 MS Partner Network)和“Microsoft Office 365 ProPlus”,但它们似乎都没有与 Microsoft.ACE.OLEDB.12.0 OLEDB 提供程序一起提供。此外,据我所知,唯一可供下载的 Microsoft Access Database Engine 2010 Redistributable 版本是 SP2(2013 年 7 月 22 日发布),因此很难在开发环境中对其进行测试!
关于multithreading - 多线程场景中的 Microsoft.ACE.OLEDB.12.0 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37432816/