Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果之前调用了CancelIo,ReadDirectoryChangesW将失败,并出现错误995_C++_Winapi_Readdirectorychangesw - Fatal编程技术网

C++ 如果之前调用了CancelIo,ReadDirectoryChangesW将失败,并出现错误995

C++ 如果之前调用了CancelIo,ReadDirectoryChangesW将失败,并出现错误995,c++,winapi,readdirectorychangesw,C++,Winapi,Readdirectorychangesw,我对ReadDirectoryChangesW的奇怪行为感到困惑,因为错误995失败了。下面解释的场景 FileHandle是使用CreateFileW获得的 在步骤1中获得的文件句柄已在ReadDirectoryChangesW中使用。它成功地将请求发送到服务器 轮询10秒,如果服务器未生成更改通知,请使用cancelIo取消chnagenotify请求。它发送cancel&服务器响应 现在,再次使用在步骤1中获得的文件句柄设置change notify with ReadDirectoryC

我对ReadDirectoryChangesW的奇怪行为感到困惑,因为错误995失败了。下面解释的场景

  • FileHandle是使用CreateFileW获得的

  • 在步骤1中获得的文件句柄已在ReadDirectoryChangesW中使用。它成功地将请求发送到服务器

  • 轮询10秒,如果服务器未生成更改通知,请使用cancelIo取消chnagenotify请求。它发送cancel&服务器响应

  • 现在,再次使用在步骤1中获得的文件句柄设置change notify with ReadDirectoryChangesW,它将失败,并显示“995-由于线程退出或应用程序请求,I/O操作已中止。” 此步骤未向服务器发送任何实际请求

  • 使用步骤1中获得的文件句柄立即再次调用ReadDirectoryChangesW&它成功并向服务器发送请求

  • 步骤3、4、5在循环中重复&每个备用ReadDirectoryChangesW都会以995失败,下一个会成功

    有人能告诉我发生了什么事吗?下面是代码

    void setnotify(WCHAR* _path)
    {
        OVERLAPPED _overlapped;
        HANDLE     _handle;
        char       _buffer[8192] = {0};
        DWORD      _bufferSize = 8192;
        CnState    _state = CN_READY;
        DWORD      _inactivityTime = 0;
    
        typedef enum State
        {
            CN_READY,
            CN_REQUEST_PENDING,
            CN_RESPONSE_RECEIVED,
            CN_REQUEST_CANCELLED
        } CnState;
    
        _handle = CreateFileW(_path,
                GENERIC_READ, // access
                FILE_SHARE_READ |
                FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, // share
                NULL, // sec
                OPEN_EXISTING, // disp
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
                0);
        if (_handle == INVALID_HANDLE_VALUE)
        {
            exit(-1);
        }
    
        memset(&_overlapped, 0, sizeof(OVERLAPPED));
    
        if (!ReadDirectoryChangesW(_handle,
                    _buffer,
                    _bufferSize,
                    true,
                    0x255,
                    NULL,
                    &_overlapped,
                    NULL)) {
    
            exit(-1);
        } else {
            _state = CN_REQUEST_PENDING;
            wprintf(L"Sent Change notify to Server\n");
        }
    
    
        while (1)
        {
            if ((_state == CN_REQUEST_PENDING) && (HasOverlappedIoCompleted(&_overlapped))) {
                wprintf(L"Response Received from Server\n");
                _state = CN_RESPONSE_RECEIVED;
            }
    
            if ((_state == CN_RESPONSE_RECEIVED) || (_state == CN_REQUEST_CANCELLED)) {
                memset(&_overlapped, 0, sizeof(OVERLAPPED));
                _inactivityTime = 0;
                if (!ReadDirectoryChangesW(_handle,
                            _buffer,
                            _bufferSize,
                            true,
                            255,
                            NULL,
                            &_overlapped,
                            NULL)) {
    
                    wprintf(L"Sent Change notify to Server Failed.\n");
                } else {
                    wprintf(L"Sent Change notify to Server\n");
                    _state = CN_REQUEST_PENDING;
                }
            }
    
            if ((_state == ChangeNotifyRequest::CN_REQUEST_PENDING) &&
                    (_inactivityTime >= 5000)){
                if (CancelIo(_handle)) {
                    _state = CN_REQUEST_CANCELLED;
                    wprintf(L"Cancelled Pending Requests.\n");
                } else {
                    wprintf(L"Cancelled failed");
                }
    
            }
    
            Sleep(50);
            _inactivityTime += 50;
    
        }
    }
    
    以下是O/p示例:

    已将更改通知发送到服务器

    已取消挂起的请求

    已将更改通知发送到服务器

    已取消挂起的请求

    向服务器发送更改通知失败

    已将更改通知发送到服务器

    已取消挂起的请求

    向服务器发送更改通知失败

    已将更改通知发送到服务器

    已取消挂起的请求

    向服务器发送更改通知失败


    已将更改通知发送到服务器

    您启动一个操作,然后取消它,因此它的完成事件将报告一个
    错误\u操作被中止
    (995)错误。但是,在收到该事件之前,您正在启动一个新操作。当您调用
    CancelIo()
    时,它只是一个取消请求,原始操作仍处于挂起状态,实际取消可能需要一段时间(或者在处理取消请求之前它可能会成功完成)。因此,您仍然需要等待取消的操作实际完成,然后处理结果,无论结果是好是坏,然后再开始下一个操作

    另外,代码中还有另外两个bug

    首次调用
    ReadDirectoryChangesW()
    时,将
    dwNotifyFilter
    参数设置为
    0x255
    ,这是错误的。实际上,您只请求这些过滤器位:

    FILE_NOTIFY_CHANGE_FILE_NAME
    FILE_NOTIFY_CHANGE_ATTRIBUTES
    FILE_NOTIFY_CHANGE_LAST_WRITE
    FILE_NOTIFY_CHANGE_CREATION
    
    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
    
    随后的调用将
    dwNotifFilter
    设置为
    255
    ,这将有效地请求这些过滤位:

    FILE_NOTIFY_CHANGE_FILE_NAME
    FILE_NOTIFY_CHANGE_ATTRIBUTES
    FILE_NOTIFY_CHANGE_LAST_WRITE
    FILE_NOTIFY_CHANGE_CREATION
    
    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
    
    因此,您的筛选是不一致的。首先,你真的不应该使用“神奇数字”。Win32 API为可用标志定义了
    #常量,您应该按照预期的方式使用它们

    最后,您没有将来自
    CreateEvent()
    的事件对象与重叠的
    结构相关联。当您不使用I/O完成端口或I/O完成回调时,文档中明确说明了此要求

    请尝试类似以下内容:

    void setnotify(WCHAR* _path)
    {
        typedef enum State
        {
            CN_READY,
            CN_REQUEST_PENDING,
            CN_REQUEST_COMPLETE
        } CnState;
    
        OVERLAPPED  _overlapped = {0};
        HANDLE      _handle;
        char        _buffer[8192];
        DWORD       _bufferSize;
        CnState     _state = CN_READY;
        DWORD       _inactivityTime;
        const DWORD _filter = 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;
    
        _handle = CreateFileW(_path,
                GENERIC_READ, // access
                FILE_SHARE_READ |
                FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, // share
                NULL, // sec
                OPEN_EXISTING, // disp
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
                0);
        if (_handle == INVALID_HANDLE_VALUE)
        {
            wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        _overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (_overlapped.hEvent == NULL)
        {
            wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        do
        {
            switch (_state)
            {
                case CN_READY:
                {
                    _bufferSize = 0;
                    _inactivityTime = 0;
    
                    if (!ReadDirectoryChangesW(_handle,
                            _buffer,
                            sizeof(_buffer),
                            TRUE,
                            _filter,
                            &_bufferSize,
                            &_overlapped,
                            NULL))
                    {
                        wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
                        exit(-1);
                    }
    
                    _state = CN_REQUEST_PENDING;
                    wprintf(L"Change notify requested from Server\n");
    
                    break;
                }
    
                case CN_REQUEST_PENDING:
                {
                    if (HasOverlappedIoCompleted(&_overlapped))
                    {
                        _state = CN_REQUEST_COMPLETE;
                    }
                    else if (_inactivityTime >= 5000)
                    {
                        if (CancelIo(_handle))
                        {
                            _state = CN_REQUEST_COMPLETE;
                            wprintf(L"No response in 5 seconds. Cancelling pending request\n");
                        }
                        else
                            wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
                    }
                    else
                    {
                        Sleep(50);
                        _inactivityTime += 50;
                    }
    
                    break;
                }
    
                case CN_REQUEST_COMPLETE:
                {
                    if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
                    {
                        wprintf(L"Response received from Server\n");
                        // use _buffer up to _bufferSize bytes as needed...
                    }
                    else if (GetLastError() == ERROR_OPERATION_ABORTED)
                    {
                        wprintf(L"Pending request cancelled\n");
                    }
                    else
                    {
                        wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
                        // handle error as needed...
                    }
    
                    _state = CN_READY:
                    break;
                }
            }
        }
    }
    
    但是,如果您不打算使用I/O完成端口或I/O完成回调,您可以通过以下事实大大简化代码:您可以通过等待事件对象发出信号来更有效地等待
    OVERLAPPED
    结果,而不必轮询循环中的
    OVERLAPPED
    状态:

    void setnotify(WCHAR* _path)
    {
        OVERLAPPED  _overlapped = {0};
        HANDLE      _handle;
        char        _buffer[8192];
        DWORD       _bufferSize;
        const DWORD _filter = 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;
    
        _handle = CreateFileW(_path,
                GENERIC_READ, // access
                FILE_SHARE_READ |
                FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, // share
                NULL, // sec
                OPEN_EXISTING, // disp
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
                0);
        if (_handle == INVALID_HANDLE_VALUE)
        {
            wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        _overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (_overlapped.hEvent == NULL)
        {
            wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        do
        {
            _bufferSize = 0;
    
            if (!ReadDirectoryChangesW(_handle,
                _buffer,
                sizeof(_buffer),
                TRUE,
                _filter,
                &_bufferSize,
                &_overlapped,
                NULL))
            {
                wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
                exit(-1);
            }
    
            wprintf(L"Change notify requested from Server\n");
    
            // alternatively, use GetOverlappedResultEx() with a timeout
            // instead of WaitForSingleObject() and GetOverlappedResult()
            // separately...
    
            if (WaitForSingleObject(_overlapped.hEvent, 5000) == WAIT_TIMEOUT)
            {
                if (CancelIo(_handle))
                    wprintf(L"No response in 5 seconds. Cancelling pending request\n");
                else
                    wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
            }
    
            if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
            {
                wprintf(L"Response received from Server\n");
                // use _buffer up to _bufferSize bytes as needed...
            }
            else if (GetLastError() == ERROR_OPERATION_ABORTED)
            {
                wprintf(L"Pending request cancelled\n");
            }
            else
            {
                wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
                // handle error as needed...
            }
        }
        while (true);
    }
    

    另外,请参阅至,它解释了在使用
    ReadDirectoryChangesW()
    时必须注意的一些其他问题,特别是
    错误的处理\u NOTIFY\u ENUM\u DIR
    错误。

    您启动一个操作,然后取消它,因此它的完成事件将报告一个
    错误\u操作中止的错误。但是,在收到该事件之前,您正在启动一个新操作。当您调用
    CancelIo()
    时,它只是一个取消请求,原始操作仍处于挂起状态,实际取消可能需要一段时间(或者在处理取消请求之前它可能会成功完成)。因此,您仍然需要等待取消的操作实际完成,然后处理结果,无论结果是好是坏,然后再开始下一个操作

    另外,代码中还有另外两个bug

    首次调用
    ReadDirectoryChangesW()
    时,将
    dwNotifyFilter
    参数设置为
    0x255
    ,这是错误的。实际上,您只请求这些过滤器位:

    FILE_NOTIFY_CHANGE_FILE_NAME
    FILE_NOTIFY_CHANGE_ATTRIBUTES
    FILE_NOTIFY_CHANGE_LAST_WRITE
    FILE_NOTIFY_CHANGE_CREATION
    
    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
    
    随后的调用将
    dwNotifFilter
    设置为
    255
    ,这将有效地请求这些过滤位:

    FILE_NOTIFY_CHANGE_FILE_NAME
    FILE_NOTIFY_CHANGE_ATTRIBUTES
    FILE_NOTIFY_CHANGE_LAST_WRITE
    FILE_NOTIFY_CHANGE_CREATION
    
    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
    
    因此,您的筛选是不一致的。首先,你真的不应该使用“神奇数字”。Win32 API为可用标志定义了
    #常量,您应该按照预期的方式使用它们

    最后,您没有将来自
    CreateEvent()
    的事件对象与重叠的
    结构相关联。当您不使用I/O完成端口或I/O完成回调时,文档中明确说明了此要求

    请尝试类似以下内容:

    void setnotify(WCHAR* _path)
    {
        typedef enum State
        {
            CN_READY,
            CN_REQUEST_PENDING,
            CN_REQUEST_COMPLETE
        } CnState;
    
        OVERLAPPED  _overlapped = {0};
        HANDLE      _handle;
        char        _buffer[8192];
        DWORD       _bufferSize;
        CnState     _state = CN_READY;
        DWORD       _inactivityTime;
        const DWORD _filter = 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;
    
        _handle = CreateFileW(_path,
                GENERIC_READ, // access
                FILE_SHARE_READ |
                FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, // share
                NULL, // sec
                OPEN_EXISTING, // disp
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
                0);
        if (_handle == INVALID_HANDLE_VALUE)
        {
            wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        _overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (_overlapped.hEvent == NULL)
        {
            wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        do
        {
            switch (_state)
            {
                case CN_READY:
                {
                    _bufferSize = 0;
                    _inactivityTime = 0;
    
                    if (!ReadDirectoryChangesW(_handle,
                            _buffer,
                            sizeof(_buffer),
                            TRUE,
                            _filter,
                            &_bufferSize,
                            &_overlapped,
                            NULL))
                    {
                        wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
                        exit(-1);
                    }
    
                    _state = CN_REQUEST_PENDING;
                    wprintf(L"Change notify requested from Server\n");
    
                    break;
                }
    
                case CN_REQUEST_PENDING:
                {
                    if (HasOverlappedIoCompleted(&_overlapped))
                    {
                        _state = CN_REQUEST_COMPLETE;
                    }
                    else if (_inactivityTime >= 5000)
                    {
                        if (CancelIo(_handle))
                        {
                            _state = CN_REQUEST_COMPLETE;
                            wprintf(L"No response in 5 seconds. Cancelling pending request\n");
                        }
                        else
                            wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
                    }
                    else
                    {
                        Sleep(50);
                        _inactivityTime += 50;
                    }
    
                    break;
                }
    
                case CN_REQUEST_COMPLETE:
                {
                    if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
                    {
                        wprintf(L"Response received from Server\n");
                        // use _buffer up to _bufferSize bytes as needed...
                    }
                    else if (GetLastError() == ERROR_OPERATION_ABORTED)
                    {
                        wprintf(L"Pending request cancelled\n");
                    }
                    else
                    {
                        wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
                        // handle error as needed...
                    }
    
                    _state = CN_READY:
                    break;
                }
            }
        }
    }
    
    但是,如果您不打算使用I/O完成端口或I/O完成回调,您可以通过以下事实大大简化代码:您可以通过等待事件对象发出信号来更有效地等待
    OVERLAPPED
    结果,而不必轮询循环中的
    OVERLAPPED
    状态:

    void setnotify(WCHAR* _path)
    {
        OVERLAPPED  _overlapped = {0};
        HANDLE      _handle;
        char        _buffer[8192];
        DWORD       _bufferSize;
        const DWORD _filter = 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;
    
        _handle = CreateFileW(_path,
                GENERIC_READ, // access
                FILE_SHARE_READ |
                FILE_SHARE_WRITE |
                FILE_SHARE_DELETE, // share
                NULL, // sec
                OPEN_EXISTING, // disp
                FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // flags
                0);
        if (_handle == INVALID_HANDLE_VALUE)
        {
            wprintf(L"Opening Server failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        _overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (_overlapped.hEvent == NULL)
        {
            wprintf(L"Creating Overlapped Event failed. Error: %u\n", GetLastError());
            exit(-1);
        }
    
        do
        {
            _bufferSize = 0;
    
            if (!ReadDirectoryChangesW(_handle,
                _buffer,
                sizeof(_buffer),
                TRUE,
                _filter,
                &_bufferSize,
                &_overlapped,
                NULL))
            {
                wprintf(L"Requesting change notify from Server failed. Error: %u\n", GetLastError());
                exit(-1);
            }
    
            wprintf(L"Change notify requested from Server\n");
    
            // alternatively, use GetOverlappedResultEx() with a timeout
            // instead of WaitForSingleObject() and GetOverlappedResult()
            // separately...
    
            if (WaitForSingleObject(_overlapped.hEvent, 5000) == WAIT_TIMEOUT)
            {
                if (CancelIo(_handle))
                    wprintf(L"No response in 5 seconds. Cancelling pending request\n");
                else
                    wprintf(L"No response in 5 seconds. Cancelling pending request failed. Error: %u\n", GetLastError());
            }
    
            if (GetOverlappedResult(_handle, &_overlapped, &_bufferSize, TRUE))
            {
                wprintf(L"Response received from Server\n");
                // use _buffer up to _bufferSize bytes as needed...
            }
            else if (GetLastError() == ERROR_OPERATION_ABORTED)
            {
                wprintf(L"Pending request cancelled\n");
            }
            else
            {
                wprintf(L"Change notify from Server failed. Error: %u\n", GetLastError());
                // handle error as needed...
            }
        }
        while (true);
    }
    

    另外,请参阅至,它解释了在使用
    ReadDirectoryChangesW()
    时必须注意的一些其他问题,特别是
    错误的处理。\u NOTIFY\u ENUM\u DIR
    错误。

    请显示您的代码,而不是描述它。谢谢。