2010-03-08 244 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

相關問題