3

在 64 位版本的 Windows 上连接到性能注册表时,我看到了一件奇怪的事情。整个程序停顿,调用堆栈变得不可读。长时间超时后,连接尝试中止,一切恢复正常。

唯一的解决方案是确保每次只有一个线程查询远程注册表,除非远程机器是 32 位 Windows XP, 2003, 2000 ,那么您可以使用任意数量的线程。

有没有人解释为什么会发生这种情况?我花了 2-3 天在网上搜索,但没有提出任何建议。

这是一个测试程序,先用一个线程运行(连接到64位Windows),然后去掉tmain中的注释,用4个线程运行。使用一个线程运行它可以按预期运行,使用 4 运行,在停止一段时间后返回 ERROR_BUSY (dwRet == 170)。

请记住在运行程序之前在 RegConnectRegistry 中正确设置远程计算机。

#define TOTALBYTES    8192
#define BYTEINCREMENT 4096

void PerfmonThread(void *pData)
{
    DWORD BufferSize = TOTALBYTES;
    DWORD cbData;
    DWORD dwRet;

    PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
    cbData = BufferSize;

    printf("\nRetrieving the data...");

    HKEY hKey;
    DWORD dwAccessRet = RegConnectRegistry(L"REMOTE_MACHINE",HKEY_PERFORMANCE_DATA,&hKey);

    dwRet = RegQueryValueEx( hKey,L"global",NULL,NULL,(LPBYTE) PerfData, &cbData );
    while( dwRet == ERROR_MORE_DATA )
    {
        // Get a buffer that is big enough.

        BufferSize += BYTEINCREMENT;
        PerfData = (PPERF_DATA_BLOCK) realloc( PerfData, BufferSize );
        cbData = BufferSize;

        printf(".");
        dwRet = RegQueryValueEx( hKey,L"global",NULL,NULL,(LPBYTE) PerfData,&cbData );
    }
    if( dwRet == ERROR_SUCCESS )
        printf("\n\nFinal buffer size is %d\n", BufferSize);
    else 
        printf("\nRegQueryValueEx failed (%d)\n", dwRet);

    RegCloseKey(hKey);
}

int _tmain(int argc, _TCHAR* argv[])
{
    _beginthread(PerfmonThread,0,NULL);
/*  _beginthread(PerfmonThread,0,NULL);
    _beginthread(PerfmonThread,0,NULL);
    _beginthread(PerfmonThread,0,NULL);
*/

    while(1)
    {

        Sleep(2000);
    }
}
4

2 回答 2

1

我想这一定是环境问题。我刚刚尝试过从 32 位 Windows XP Professional 到 64 位 Windows 7 Ultimate,它运行良好。偶尔在一个或两个线程上调用 RegQueryValueEx 会失败,出现 ERROR_BUSY 或 ERROR_NOT_READY,但我从未经历过任何长时间的延迟。万一其他人尝试对此进行测试,我遇到了障碍;您使用的帐户必须是 Performance Monitor Users 组的成员才能远程访问 HKEY_PERFORMANCE_DATA。还要确保远程注册表服务正在运行。

于 2010-04-01T01:49:44.873 回答
1

这不是一个真正的答案,而是一个建议。即使您只是查询注册表(而不是写入),我想知道您是否正在使用多个线程产生某种死锁。

缺乏 Windows 开发或测试环境,请接受这个建议:也许您可以在注册表调用周围使用互斥锁......如果这确实是问题,这可能会缓解任何死锁情况。

祝你好运。

于 2010-03-29T17:26:35.753 回答