多线程方案中的Microsoft.ACE.OLEDB.12.0错误 [英] Microsoft.ACE.OLEDB.12.0 bug in multithread scenario

查看:144
本文介绍了多线程方案中的Microsoft.ACE.OLEDB.12.0错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use in my x64 application the Microsoft Access Database Engine 2010 (part of Microsoft Office 2016) for working with mdb files. But, current version of Microsoft Access Database Engine 2010 (OLEDB provider Microsoft.ACE.OLEDB.12.0) have a bug. This engine crashes in multithread work. If I create two OLE DB (or ADO DB) connections with this provider in different threads, then one of them will crashed in Mso40UIwin32client.dll with exception 0xC0000005: Access violation writing location 0x0000000000000000.

异常堆栈:

  • ACEOLEDBTest.exe中的0x00007FFB32361F28引发异常:Microsoft C ++异常:内存位置处的std :: runtime_error 0x0000006B771FEAF0.
  • 在以下位置引发异常:0x00007FFB32361F28 ACEOLEDBTest.exe:Microsoft C ++异常:[重新抛出]内存 位置0x0000000000000000.
  • 在0x00007FFB32361F28引发异常 在ACEOLEDBTest.exe中:Microsoft C ++异常:在以下位置std :: runtime_error 内存位置0x0000006B771FEAF0.
  • 在抛出异常 ACEOLEDBTest.exe中的0x00007FFB32361F28:Microsoft C ++异常: 存储位置0x0000006B771FEFB8的std :: runtime_error.
  • 异常 在以下位置抛出0x00007FFAF9ED1271(Mso40UIwin32client.dll) ACEOLEDBTest.exe:0xC0000005:访问冲突写入位置 0x0000000000000000.
  • Exception thrown at 0x00007FFB32361F28 in ACEOLEDBTest.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0000006B771FEAF0.
  • Exception thrown at 0x00007FFB32361F28 in ACEOLEDBTest.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
  • Exception thrown at 0x00007FFB32361F28 in ACEOLEDBTest.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0000006B771FEAF0.
  • Exception thrown at 0x00007FFB32361F28 in ACEOLEDBTest.exe: Microsoft C++ exception: std::runtime_error at memory location 0x0000006B771FEFB8.
  • Exception thrown at 0x00007FFAF9ED1271 (Mso40UIwin32client.dll) in ACEOLEDBTest.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

具有此错误的C ++代码示例:

C++ code sample with this error:

#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平台构建此示例. 我在

You should build this sample for x64 platform with Visual C++ 2013/2015. Similar bug I found at MS forum. Can anybody help me?

推荐答案

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

We too have encountered this issue in a multi-threaded VB.Net (Framework v4.5.2) service application. After much testing, the only way we found to resolve this was to either use a single thread or turn off connection pooling (using OLE DB Services=-2). In the end we have gone with the latter as we needed the system to be able to process requests in parallel.

仅供参考,我安装的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可再发行版本是SP2(2013年7月22日发布),因此很难在开发环境中对此进行测试!

FYI, the version of Office 2016 I have installed does not include this driver (hence why our program passed any kind of basic testing) but it was included with the version of Office 2016 that our customer installed. So far I have checked "Microsoft Office Professional Plus 2016" (from both MSDN and MS Partner Network) and "Microsoft Office 365 ProPlus" and none of them appear to come with the Microsoft.ACE.OLEDB.12.0 OLEDB provider. Also, as far as I can see, the only version of the Microsoft Access Database Engine 2010 Redistributable available to download is SP2 (released 22/07/2013) so it is hard to get this tested in a development environment!

这篇关于多线程方案中的Microsoft.ACE.OLEDB.12.0错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆