2011-05-27 9 views
10

बिल्कुल के रूप में यह लग रहा है, मैं अतुल्यकालिक ReadDirectoryChangesW आईओ समापन के साथ प्रयास कर रहा हूँ और यह काम नहीं कर रहा है, विशेष रूप से, GetLastError बार-बार रिटर्न 258 (GetQueuedCompletionStatus का समय समाप्त)।अतुल्यकालिक ReadDirectoryChangesW - GetQueuedCompletionStatus हमेशा समय समाप्त

typedef struct dirinfo_struct 
{ 
    HANDLE hDirFH;   // directory handle 
    OVERLAPPED Overlapped; // overlapped storage 
    int len_buffer;   // buffer length 
    wchar_t* buffer;   // buffer itself 
    wchar_t* directory_name; // target name 
} dirinfo_t; 

typedef struct dirmon_struct 
{ 
    HANDLE hDirOPPort;  // handle to the IO port. 
    dirinfo_t* dirinfo;  // pointer to the struct above. 
} dirmon_t; 

प्रासंगिक जानकारी संग्रहीत करने के लिए:

मैं structs की है। यह initialised है:

t->hDirFH = CreateFile(L"C:\\test", 
         FILE_LIST_DIRECTORY, 
         FILE_SHARE_READ|FILE_SHARE_WRITE, 
         NULL, 
         OPEN_EXISTING, 
         FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 
         NULL); 
d->dirinfo = t; 
d->hDirOPPort = CreateIoCompletionPort(d->dirinfo->hDirFH, 
             NULL,  
             (ULONG_PTR)(d->dirinfo), 
             1); 

तो मैं एक नया धागा करने के लिए घ के माध्यम से इस जानकारी को पारित:

dirinfo_t* t = malloc(1*sizeof(dirinfo_t)); 
dirmon_t* d = malloc(1*sizeof(dirmon_t)); 
dirinfo_init(t); // does t->buffer = malloc(8192*sizeof(wchar_t)); 

तब मैं अपने निर्देशिका हैंडल और कॉम पोर्ट पैदा करते हैं। अब को कहा नई धागा मेरे पास है:

bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, lpBytes, 
            (ULONG_PTR*)d->dirinfo,  
            lpOverlapped, 1000); 

if (bResultQ) 
{ 
    bResultR = ReadDirectoryChangesW(d->dirinfo->hDirFH, 
            (void*)d->dirinfo->buffer, 
            8192, TRUE, 
            FILE_NOTIFY_CHANGE_FILE_NAME | 
            FILE_NOTIFY_CHANGE_DIR_NAME | 
            FILE_NOTIFY_CHANGE_ATTRIBUTES | 
            FILE_NOTIFY_CHANGE_SIZE | 
            FILE_NOTIFY_CHANGE_LAST_WRITE | 
            FILE_NOTIFY_CHANGE_LAST_ACCESS | 
            FILE_NOTIFY_CHANGE_CREATION | 
            FILE_NOTIFY_CHANGE_SECURITY, 
            lpReadDirBytes, 
            &d->dirinfo->Overlapped, 
            NULL); 
} 
else 
{ 
    printf("GetQueuedCompletionStatus(): Failed, "); 
    errorcode = GetLastError(); 
    printf("Error Code %d\n", errorcode); 
    Sleep(500); 
} 

तो मैं इस बंद चल रहा सेट और मैं ख़ुशी से के रूप में मैं चाहिए समय समाप्ति (258 त्रुटियों) पाने के बाद से निर्देशिका नहीं बदला है। हालांकि, भले ही मैं निर्देशिका को बदलूं, फिर भी मुझे त्रुटि संदेश मिल रहे हैं; दूसरे शब्दों में उन बदलावों को उठाया नहीं जा रहा है। जो मुझे विश्वास दिलाता है कि मुझे यह सेट गलत तरीके से मिला है।

कोई विचार?

चेतावनियां:

  • विडंबना यह है कि यह अंततः अजगर को pywin32 के माध्यम से परिवर्तित किया जाएगा। हालांकि, जब तक मैं समझ नहीं पाता कि यह सी में कैसे काम करना है, मैं वहां नहीं जा रहा हूं।
  • तुल्यकालिक ReadDirectoryChangesW एक विकल्प नहीं है। यदि कोई घटना नहीं निकाल दी जाती है, तो मुझे थ्रेड की आवश्यकता होती है जो यह टाइमआउट पर है ताकि यह जांच सके कि यह अभी भी चल रहा है या नहीं।
  • मैं विशेष रूप से सी ++ में सी में लिख रहा हूं।
  • FindFirstChangeNotification आदि कोई विकल्प नहीं है - मैं लगातार बदलकर काम करने के लिए निर्देशिका सूची की तुलना करना नहीं चाहता हूं।

अन्य नोट:

  • निर्देशिका मौजूद है, कि संभाल शून्य नहीं है। इसी तरह कॉम्पोर्ट हैंडल के लिए।
  • सब कुछ धागा

मैं कोड परियोजना से CDirectoryChangeWatcher पर एक नज़र लिया है करने के लिए पारित किया जा रहा है, लेकिन एक तरफ सी के ++ उपयोग कई और अधिक धागे, मैं नहीं देख सकते हैं कि मैं क्या अलग तरह से कर रहा हूँ। अगर मुझे कुछ याद आ रहा है तो इसे इंगित करने के लिए स्वतंत्र महसूस करें!

आउटपुट, यदि यह मदद करता है, मूल रूप से दोहराया जाता है, इससे कोई फर्क नहीं पड़ता कि मैं निर्देशिका में कितना बदलता हूं।

GetQueuedCompletionStatus(): Failed, Error Code 258 
+4

इसे अच्छी तरह से काम करने के लिए यह गैर-तुच्छ (इसे हल्के ढंग से रखने के लिए) प्राप्त करना है। यदि आपने अभी तक नहीं किया है, तो मैं जिम बेवरिज के ब्लॉग को पढ़ने पर सलाह दूंगा: http://qualapps.blogspot.com/2010/05/understanding-readdirectorychangesw.html। चेतावनी: उसका नमूना कोड सी ++ में है, लेकिन कम से कम यह अधिक से बेहतर है। चेतावनी 2: मैं निश्चित रूप से निश्चित हूं कि आप जो भी करते हैं, कोई फर्क नहीं पड़ता, ReadDirectoryChangesW वास्तव में पूरी तरह से सही ढंग से काम नहीं करेगा। मैं आमतौर पर बदले में परिवर्तन पत्रिकाओं का उपयोग करने की सलाह देता हूं। http://msdn.microsoft.com/en-us/library/aa363798.aspx। वे या तो तुच्छ नहीं हैं, लेकिन कम से कम वे काम करते हैं। –

+0

@ जेफी धन्यवाद, मैंने उसके स्रोत पर एक नज़र डाली थी, लेकिन वह (जहां तक ​​मैं देख सकता हूं) GetQueue का उपयोग नहीं करता ... या CreateIo ... उसका रीडमी वास्तव में वहां से अधिक फ़ाइलों का तात्पर्य है इसलिए मैं सोच रहा हूं उसने उन्हें हटा दिया है। मैं धीरे-धीरे इस प्राप्ति के लिए आना शुरू कर रहा हूं ... दुर्भाग्य से पत्रिकाओं को बदलने के लिए व्यवस्थापकीय विशेषाधिकारों की आवश्यकता होती है जो हमारे पास नहीं हो सकते हैं। मुझे लगता है कि मैं संभालने के लिए हमेशा एक विंडोज़ सेवा बंद कर सकता हूं। –

उत्तर

6

मैं कोड की दीवारों पोस्टिंग का एहसास आम तौर पर खराब माना जाता है, लेकिन यहाँ कैसे मैं इस काम के मिल गया है:

न्यू structs:

BOOL runthread; 

typedef struct overlapped_struct 
{ 
    OVERLAPPED overlapped; 
    wchar_t* buffer; 
} overlapped_t; 

typedef struct dirinfo_struct 
{ 

    HANDLE hDirOPPort; 
    HANDLE hDirFH; 
    overlapped_t* o; 
    int len_buffer; 
    wchar_t* buffer; 
    wchar_t* directory_name; 
    ULONG_PTR CompletionKey; 
} dirinfo_t; 

int somekey = 1; 

आवंटन तरीके:

void dirinfo_init(dirinfo_t* t) 
{ 
    t->buffer = malloc(16777216*sizeof(wchar_t)); 
    t->len_buffer = 16777216; 
    t->o = calloc(1, sizeof(overlapped_t)); 
    t->o->buffer = calloc(16777216, sizeof(wchar_t)); 
    memset(t->o->buffer, 0, 16777216); 
    memset(t->o, 0, sizeof(OVERLAPPED)); 
} 

void dirinfo_free(dirinfo_t* t) 
{ 
    free(t->buffer); 
    free(t->o->buffer); 
    free(t->o); 
    free(t); 
} 

महत्वपूर्ण सामग्री main() से यह करता है:

dirinfo_t* d = malloc(1*sizeof(dirinfo_t)); 
d->CompletionKey = (ULONG_PTR)&somekey; 
dirinfo_init(d); 

/* set up */ 
runthread = TRUE; 
d->hDirFH = CreateFile(L"C:\\hydratest", 
       FILE_LIST_DIRECTORY, 
       FILE_SHARE_READ|FILE_SHARE_WRITE, 
       NULL, 
       OPEN_EXISTING, 
       FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 
       NULL); 

d->hDirOPPort = CreateIoCompletionPort(d->hDirFH, NULL, 
         (ULONG_PTR)d->CompletionKey, 1); 

अंत में मेरा प्रतीक्षा धागा। यहां कुंजी है: मैं एक ओवरलैप्ड संरचना को पास नहीं कर रहा हूं। मैं एक संरचना में गुजर रहा हूं जिसमें OVERLAPPED और wchar_t आधारित संग्रहण की उचित मात्रा है। कारणों से मैं पूरी तरह से समझ नहीं पा रहा हूं, यह काम करता है। संपादित करेंthis answer देखें। मेरा मानना ​​है कि डेटा क्षेत्र यहां ओवरलैप्ड बफर के रूप में कार्य करता है।

DWORD WINAPI WaitingThread(void* args) 
{ 
    DWORD errorcode = 0; // an error code 
    BOOL bResultQ = FALSE; // obvios=us 
    BOOL bResultR = FALSE; 
    DWORD NumBytes = 0; 
    FILE_NOTIFY_INFORMATION* pInfo = NULL; // the data incoming is a pointer 
              // to this struct. 
    int i = 0; 
    dirinfo_t* d = (dirinfo_t*) args;  // rescue struct from thread arg. 

फिर हम मुख्य धागे पर पहुंच जाते हैं। परीक्षण और त्रुटि से पता चलता है कि आपको ReadDirectoryW और GetQueueCompletionStatus दोनों को कॉल करना होगा। मुझे लगता है कि इसका क्या अर्थ है कि हम ReadDirectoryChangeW ** से बफर को स्पर्श नहीं करना चाहते हैं ** जब तक हमें बताया जाता है कि हम GetQueue तक कर सकते हैं। हालांकि उस परिकल्पना पर सुधार स्वागत है।

while (runthread) 
    { 
     bResultR = ReadDirectoryChangesW(d->hDirFH, (void*)d->buffer, 
              16777216, TRUE, 
       FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | 
       FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | 
       FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | 
       FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, 
              NULL, 
              &d->o->overlapped, 
              NULL); 
     bResultQ = GetQueuedCompletionStatus(d->hDirOPPort, 
              &NumBytes, &(d->CompletionKey), 
              (LPOVERLAPPED*)(d->o), 1000); 

तो, अब हम उन कार्यों हम तो परीक्षण वे दोनों सच लौटे कि कहा जाता है की है,। बड़ी बदसूरत चेतावनी यदि आपके पास पैरामीटर सेट किए गए हैं तो bResultR हमेशा सत्य लौटाता है, या ऐसा लगता है कि यह मुझे लगता है। bResultQ हालांकि पोर्ट पर नया डेटा है या नहीं, इस पर निर्भर करता है।

 if (bResultQ && bResultR) 
     { 

तो यहां हम ReadDirectoryChangesW से है कि बफर डाली और struct से जानकारी का उपयोग।

  wprintf(L"\n"); 
      pInfo = (FILE_NOTIFY_INFORMATION*) d->buffer; 
      wprintf(L"File %s", pInfo->FileName); 
      wprintf(L" changes %d\n", pInfo->Action); 
      memset(d->buffer, 0, 16777216); 
     } 

अन्यथा, और thanks to Tony for this, आप सुरक्षित रूप WAIT_TIMEOUT अनदेखा कर सकते हैं त्रुटियों, लेकिन कुछ और शायद मतलब है कि आप मुसीबत में हैं।

 else 
     { 
      errorcode = GetLastError(); 

      if (errorcode == WAIT_TIMEOUT) 
      { 
       printf("GetQueuedCompletionStatus(): Timeout\n"); 
      } 
      else 
      { 
       printf("GetQueuedCompletionStatus(): Failed\n"); 
       printf("Error Code %d\n", errorcode); 
      } 
      Sleep(500); 
     } 
    } 

    return 0; 
} 

और जो मुझे लगता है वह एक कामकाजी उदाहरण है जो पूरा करता है।

कुछ नोट:

  • मैं बफर आकार निर्धारित किया है विशाल होने के लिए। मैंने 100 फाइलों की प्रतिलिपि देखी है या इसलिए कि बफर अंतरिक्ष सेट से 8192 पर चला गया और यहां और वहां एक आइटम या दो से चूक गया। तो मुझे उम्मीद नहीं है कि यह हमेशा सबकुछ उठाएगा। मेरा समाधान हर 100 घटनाओं को कहना होगा, फ़ाइल विधि पेड़ को सत्यापित करें जो आपको लगता है कि यह विधि का उपयोग कर रहा है। हालांकि, असीम रूप से बेहतर समाधान, संभावित रूप से संभावित बड़े पेड़ की गणना करने के लिए।
+0

हम्म दिलचस्प। निश्चित रूप से इस आईओ सामान एक साहसिक। :) पोस्ट करने का शुक्रिया। –

+0

@Ninefingers: नमस्ते, इसी तरह के प्रोजेक्ट पर काम कर रहा हूं (लेकिन सी ++ में) और मेरी समस्या है कि मैं अपने आवेदन थ्रेड से निर्देशिका निर्देशिका थ्रेड को अलग करना चाहता हूं, अगर आपको कोई फर्क नहीं पड़ता कि आपने मुझे 'प्रतीक्षा थ्रेड' कहा है तो मैं इसे जोड़ता हूं आपका मुख्य कोड लेकिन मुझे अभी भी एक ही समस्या है, अग्रिम धन्यवाद। – Oumaya

+0

@ एंटनी कृपया समझाएं: malloc (16777216 * sizeof (wchar_t)) जैसा कि मुझे लगता है कि 16777216 = 8192 * 2048 => यह 2048 क्या है? धन्यवाद! – Edward83

1

नोट: ठीक से GetQueuedCompletionStatus से त्रुटियों को पकड़ने के लिए, के रूप में यह निर्धारित करने के लिए है कि इस समारोह वास्तव में लौट आए, किया जाना चाहिए के रूप में इस मुश्किल है:

उदाहरण:

DWORD dwNumBytes; 
ULONG_PTR CompletionKey; 
OVERLAPPED* pOverlapped; 

//hIOCP is initialized somewhere else in the program 
BOOL bOK = GetQueuedCompletionStatus(hIOCP, &dwNumBytes, &CompletionKey, &pOverlapped, 1000); 

DWORD dwError = GetLastError(); 

if(bOK) 
{ 
// Process a successfully completed I/O event. 
} 
else 
{ 
    if (pOverlapped != NULL) 
    { 
    // Process a failed completed I/O request 
    //dwError contains the reason for failure 
    } 
    else { 
     if (dwError == WAIT_TIMEOUT) 
     { 
     //Time-out while waiting for completed I/O entry. 
     } 
     else { 
      //Bad call to GetQueuedCompletionStatus 
      //dwError contains the reason for the bad call. 
     } 
} 

उदाहरण से लिया पुस्तक (सी/सी ++ के माध्यम से विंडोज) कृपया अपने कोड में इस त्रुटि को संभालने का प्रयास करें।

इसके अलावा "... GetQueuedCompletionStatus पर कॉल करने वाले धागे अंतिम-प्रथम (एलआईएफओ) फैशन में जागृत हो जाते हैं।" एक को

जब अतुल्यकालिक डिवाइस प्रदर्शन मैं/हे, तो आपको पता गुजरना होगा प्रारंभ ओवरलैप संरचना के माध्यम से पैरामीटर pOverlapped:

संरचना ओवरलैप। इस संदर्भ में "ओवरलैप" शब्द का अर्थ है कि I/O प्रदर्शन करने में व्यतीत समय आपके थ्रेड व्यय को अन्य कार्यों को करने के समय को ओवरलैप करता है।

यह पैरामीटर के बारे में बात कर रहा है, जब आप बस ऊपर के लिए एक नोट है, जो इस संरचना प्रारंभ किए जाने की आवश्यकता के रूप में WriteFileReadFile या कहते हैं।

यह इस प्रकार के रूप में दिखता है:

typedef struct _OVERLAPPED { 
    ULONG_PTR Internal; 
    ULONG_PTR InternalHigh; 
    union { 
    struct { 
     DWORD Offset; 
     DWORD OffsetHigh; 
    }; 
    PVOID Pointer; 
    }; 
    HANDLE hEvent; 
} OVERLAPPED, *LPOVERLAPPED; 

नोट: आप अपने CreateIoCompletionPort समारोह के अपने dwCompletionKey पैरामीटर के लिए एक struct के लिए सूचक गुजर रहे हैं। संदर्भ में मैं देख रहा हूं कि वे केवल स्थिर (#define CK_FILE 1) पास करते हैं। ऐसा कहता है कि आप जो भी चाहें पारित कर सकते हैं, क्योंकि ओएस परवाह नहीं है। बस इसे इंगित करना चाहता था।

+0

इसके लिए बहुत बहुत धन्यवाद, अब मुझे वास्तव में संभावित रूप से डेटा रखने में विफलता की उम्मीद है ...! मैंने ज़ीरोमोरीरी होने के लिए अपनी ओवरलैप्ड स्ट्रक्चर को संशोधित कर दिया है, मैंने निरंतर मूल्य पर पूर्णता की पुष्टि की है, आदि। फिर भी, हर बार जब मुझे शून्य ओवरलैप्ड संरचना, झूठी वापसी मान और टाइमआउट त्रुटि कोड मिलता है। –

+0

एमएसडीएन से: "अगर GetQueuedCompletionStatus को कॉल विफल हो जाता है क्योंकि कॉल बकाया होने पर पूरा होने वाला पूरा पोर्ट बंद हो जाता है, तो फ़ंक्शन FALSE लौटाता है, * lpOverlapped पूर्ण होगा, और GetLastError ERROR_ABANDONED_WAIT_0 लौटाएगा।" –

+0

न्यूमबाइट्स मूल्य के बारे में क्या, यह लौटने पर भर जाता है? –

संबंधित मुद्दे