2010-03-08 113 views
3

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

唯一的解决方案是确保当时只有一个线程在查询远程注册表,除非远程计算机是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); 
    } 
} 
+0

什么窗户? XP?你是否也尝试过使用不同的64位安装(另一台机器)?你是从32位机器查询吗? (XP?Vista?)如何从另一台(或同一台)64位机器查询64位机器? – vladr 2010-03-29 16:19:30

+0

问题是,32位应用程序试图同时访问多个线程的64位Windows版本。如果程序主机是64位或32位Windows,则无关紧要。据我所知,这适用于所有64位版本的Windows。 – ROAR 2010-03-30 07:31:01

回答

1

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

由于缺乏Windows开发或测试环境,请对其价值提出以下建议:也许您可以在注册表调用周围使用互斥锁...即可以减少任何死锁情况,如果这确实是问题。

祝你好运。

+0

这个问题,与32位机器同时注册表连接的作品会膨胀,当你指向一个64位机器完全相同的程序时,应用程序“挂起”在未定义的状态。 “解决方案”是确保当时只有一个注册表调用被执行。但是微软文档没有提到这个“限制”,所以我首先打开这个问题,找出是否有人知道这里发生了什么。 – ROAR 2010-03-30 07:34:18

1

我认为这肯定是一个环境问题。我只是从32位Windows XP专业版到64位Windows 7旗舰版尝试了这一点,并且它工作正常。偶尔在一两个线程上调用RegQueryValueEx会失败,ERROR_BUSY或ERROR_NOT_READY,但我从来没有经历过任何长时间的延迟。如果有人试图测试这个,我遇到了一个障碍;您使用的帐户必须是Performance Monitor Users组的成员才能远程访问HKEY_PERFORMANCE_DATA。同时确保远程注册表服务正在运行。

+0

长时间的停顿可能是主观的,但问题是注册表连接超时ERROR_BUSY(如你注意到的),如果两个同时打开,这也是我的问题,如果有人有任何未记录/限制的限制。 感谢您的测试! – ROAR 2010-04-01 11:00:58

+0

那么,在处理网络操作时,接收ERROR_BUSY似乎是合理的。也许微软调低了Vista上同时进行的远程注册表操作的次数。我没有尝试使用32位远程机器,但也许稍后我会看看我是否得到类似的行为。如果你对解决这个问题真的很疯狂,你可以编写自己的远程注册表服务;微软已经发布(或更可能被迫发布)规范 - http://msdn.microsoft.com/en-us/library/cc244877.aspx – Luke 2010-04-01 11:35:36

+0

我刚刚尝试使用32位Windows 7旗舰版,我有更多的问题与64位版本相比。由于某种原因返回的数据更大,因此需要多次尝试;这给错误发生带来了更大的机会。不过,我认为这个问题并不是特定于32位和64位的。 – Luke 2010-04-01 12:54:01