Multithreading 多线程场景中的Microsoft.ACE.OLEDB.12.0错误

Multithreading 多线程场景中的Microsoft.ACE.OLEDB.12.0错误,multithreading,ms-access,visual-c++,ms-office,oledb,Multithreading,Ms Access,Visual C++,Ms Office,Oledb,我在x64应用程序(Microsoft Office 2016的一部分)中使用mdb文件。 但是,当前版本的MicrosoftAccess数据库引擎2010(OLEDB提供程序Microsoft.ACE.OLEDB.12.0)有一个bug。 此引擎在多线程工作中崩溃。 如果我在不同的线程中创建了两个与此提供程序的OLE DB(或ADO DB)连接,则其中一个连接将在Mso40UIwin32client.dll中崩溃,异常为0xC0000005:访问冲突写入位置0x0000000000000000

我在x64应用程序(Microsoft Office 2016的一部分)中使用mdb文件。 但是,当前版本的MicrosoftAccess数据库引擎2010(OLEDB提供程序Microsoft.ACE.OLEDB.12.0)有一个bug。 此引擎在多线程工作中崩溃。 如果我在不同的线程中创建了两个与此提供程序的OLE DB(或ADO DB)连接,则其中一个连接将在
Mso40UIwin32client.dll
中崩溃,异常为0xC0000005:访问冲突写入位置0x0000000000000000

异常堆栈:

  • ACEOLEDBTest.exe中0x00007FFB32361F28处引发异常:Microsoft C++异常:STD::运行时内存错误 0x0000006B771FEAF0
  • 在中的0x00007FFB32361F28处引发异常 ACEOLEDBTest.exe:微软C++异常:[重新扔]在内存中 位置0x0000000000000000
  • 在0x00007FFB32361F28处引发异常 在ACEOLEDBTest.exe中:微软C++异常:STD::RunTimeIn错误 内存位置0x0000006B771FEAF0
  • 抛出异常 0x09007FFB32661F28在ACEOLEDBTest.exe:微软C++例外: std::内存位置0x0000006B771EFB8处的运行时错误
  • 例外情况 在中的0x00007FFAF9ED1271(Mso40UIwin32client.dll)处引发 ACEOLEDBTest.exe:0xC0000005:访问冲突写入位置 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;
}
#包括“stdafx.h”

#包括。有人能帮我吗?

我们在一个多线程VB.Net(Framework v4.5.2)服务应用程序中也遇到了这个问题。经过大量测试后,我们发现解决此问题的唯一方法是使用单个线程或关闭连接池(使用OLE DB Services=-2)。最后,我们使用了后者,因为我们需要系统能够并行处理请求


仅供参考,我安装的Office 2016版本不包含此驱动程序(因此我们的程序通过了任何类型的基本测试),但它包含在客户安装的Office 2016版本中。到目前为止,我已经检查了“Microsoft Office Professional Plus 2016”(来自MSDN和MS合作伙伴网络)和“Microsoft Office 365 ProPlus”,但没有一个是Microsoft.ACE.OLEDB.12.0 OLEDB提供商提供的。此外,据我所知,可供下载的Microsoft Access数据库引擎2010可再发行版的唯一版本是SP2(发布于2013年7月22日),因此很难在开发环境中对其进行测试

23W,听起来你下定决心要让它发挥作用,但是你在微软论坛的帖子中收到了一些非常好的答案,这些帖子是你之前在同一个主题上创建的。从这个线程,我相信不可能多线程访问数据库实例。这就像是试图将一个“75”Trabant发射到轨道上。我可以温和地建议,找到一种替代方法对您更有利吗?@kismert,OLE DB在多线程应用程序中工作得很成功。Access DB也可以在多线程应用程序中工作。如果您阅读了,那么您可以看到此错误的修补程序解决方案,但我的应用程序是以模块结构构建的,我无法预测何时调用访问提供程序,因此我无法从应用程序启动中的访问连接创建虚拟存根。好的,部分解决方案自行工作。还有一些未命名的修补程序可能会修复/破坏代码。但这与问题无关。对我来说,作为一个老程序员,你所描述的是一个不能依赖于可预测的协同工作的组合。简而言之,它不起作用。因此,即使你希望“理想”的方法发挥作用,我再次温和地建议你放弃这种方法,找到一些更简单、可靠的解决方案。