0

I'am using ReadDirectoryChangesW to watch a directory changes asynchronously, based on this question I implement a function that watch a given directory, but I still get the error message GetQueuedCompletionStatus(): Timeout

void Filewatcher::OpenWatchDir(QString PathToOpen)
{

    QString path=QDir::fromNativeSeparators(PathToOpen);

    LPCTSTR  Dirname=(LPCTSTR)path.utf16();//.toStdWString().c_str();

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

    /* set up */
    runthread = TRUE;
    d->hDirFH = CreateFile(Dirname,
                    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);

    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;

    while ( runthread )
        {
            bResultR = ReadDirectoryChangesW(d->hDirFH, (void*)d->buffer,
                                              16777216, TRUE,
                   FILE_NOTIFY_CHANGE_FILE_NAME  | FILE_NOTIFY_CHANGE_CREATION  ,
                                              NULL,
                                              &d->o->overlapped,
                                              NULL );
            bResultQ = GetQueuedCompletionStatus(d->hDirOPPort,
                                                 &NumBytes, &(d->CompletionKey),
                                                 (LPOVERLAPPED*)(d->o), 1000);
            if ( bResultQ && bResultR )
                    {
                wprintf(L"\n");
                pInfo = (FILE_NOTIFY_INFORMATION*) d->buffer;
                wprintf(L"File %s", pInfo->FileName);
                wprintf(L" changes %d\n", pInfo->Action);

                qDebug()<<"file  "<<pInfo->FileName<<" was"<<pInfo->Action;
                memset(d->buffer, 0, 16777216);
            }
            else
                   {
                       errorcode = GetLastError();

                       if ( errorcode == WAIT_TIMEOUT )
                       {
                           qDebug()<<"GetQueuedCompletionStatus(): Timeout\n";
                       }
                       else
                       {
                           qDebug()<<"GetQueuedCompletionStatus(): Failed\n";
                           qDebug()<<"Error Code "<<errorcode;
                       }
                       Sleep(500);
                   }
               }


}

I need to know how use ReadDirectoryChangesW asynchronously with IoCompletionPort.

Any help please.

Community
  • 1
  • 1
Oumaya
  • 655
  • 4
  • 18
  • 43
  • 3
    Perhaps the directory didn't change in that one second you passed as a timeout? – avakar Oct 15 '12 at 14:27
  • I change it to 10000 millsec I can see now my events, but my problem now is that I can't handle my application any more (the call wasn't in a separate thread), I thought that was the point of working with `ReadDirectoryChangesW` asynchronously.How can I seperate my application thread from watching directory thread? – Oumaya Oct 15 '12 at 14:46
  • oumaya: The point is that you can wait on the completion port and other objects at the same time, even GUI messages, using `(Msg)WaitForMultipleObjects(Ex)`. So you can do other useful work while waiting for the completion port. – Ben Voigt Oct 15 '12 at 15:49
  • Well, in Qt, you have very little option but to run it in a separate thread. Normally, you would integrate the wait into your message pump, but there is no provision for that in Qt, unfortunately. – avakar Oct 15 '12 at 15:51
  • @avakar: So Qt has no equivalent to `XtAddAppInput`, to get new handles/file descriptors into the wait loop? How did it ever gain a following when it doesn't support basic operations that both Win32 and Unix toolkits have had for decades? – Ben Voigt Oct 15 '12 at 15:54
  • @BenVoigt, well, if you find an equivalent, please do share. – avakar Oct 15 '12 at 15:58
  • @avakar: Found and added to my answer. – Ben Voigt Oct 15 '12 at 16:01

2 Answers2

2

There's no reason to use a completion port here, simple overlapped I/O with an event will work fabulously.

The key is to wait for this operation (whether event or completion port) at the same time as all other events (possibly including GUI messages), and only check the status when the event becomes signaled. For that, use (Msg)WaitForMultipleObjects(Ex).

In Qt, you can add Win32 events (used by OVERLAPPED structure for async I/O) using QWinEventNotifier as described here:

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Note that `QWinEventNotifier` is missing from several recent versions of Qt. see http://code.google.com/p/qextserialport/issues/detail?id=91 – avakar Oct 15 '12 at 16:13
  • @avakar: No, it's not missing. It just moved. And in Qt 5 it moved again, to become a public API. At least if that blog post can be believed. – Ben Voigt Oct 15 '12 at 16:20
  • Thank you both for your answers, in fact am working with QT 4.7.4, so as the article posts I can use `QWinEventNotifier` legally. I will try to proceed like the author said _make a new QThread subclass that does nothing except call the Windows WaitForSingleObject() function (or WaitForMultipleObjects() or any variants) in an infinite loop. Set it up so the call to the Windows function blocks until an event occurs, and emit a signal from the thread whenever something happens. Then you can connect that signal to a slot in your program_ I'am newbie so how to block it until an event occurs? – Oumaya Oct 16 '12 at 07:46
0

thank you guys for your answers, after a deep research and retesting code I solve my problem based on this , I really appreciate your help.

Oumaya
  • 655
  • 4
  • 18
  • 43