보류 중인 I/O 작업 취소 - Win32 앱 (2023)

  • 기사
  • 읽는 데 12분

사용자가 느리거나 중단된 I/O 요청을 취소하도록 허용하면 애플리케이션의 유용성과 견고성을 향상시킬 수 있습니다. 예를 들어열린 문서매우 느린 장치 호출이기 때문에 함수 블록을 호출하는 경우 호출을 취소하면 애플리케이션을 종료하지 않고 새 매개변수로 다시 호출할 수 있습니다.

Windows Vista는 취소 기능을 확장하고 동기식 취소 작업에 대한 지원을 추가합니다.

참조취소IoEx함수를 호출해도 I/O 작업이 중단되지 않습니다. 작업을 수행하는 드라이버는 취소를 지원해야 하며 작업은 취소 가능한 상태여야 합니다.

취소 고려사항

취소 통화를 예약할 때 다음 사항에 유의하십시오.

  • 기본 드라이버가 취소를 올바르게 지원한다는 보장은 없습니다.
  • 비동기 I/O를 취소하는 경우취소IoEx함수에 겹치는 구조가 없으면 프로세스의 모든 스레드에서 보류 중인 파일 I/O를 취소하려고 시도합니다. 각 스레드는 개별적으로 처리되기 때문에 처리 후 다른 모든 스레드가 파일에 대한 I/O를 취소하기 전에 하나의 스레드가 파일에 대한 다른 I/O를 초기화하여 타이밍 문제를 일으킬 수 있습니다.
  • 비동기 I/O를 재정의할 때 대상 재정의와 함께 겹치는 프레임워크를 사용하지 마십시오. I/O 작업이 완료되면(성공 또는 취소) 오버레이 구조는 시스템에서 더 이상 사용되지 않으며 재사용할 수 있습니다.
  • 동기 I/O를 취소하는 경우취소동기 Io함수를 호출하면 스레드가 현재 동기 호출을 취소하려고 시도합니다. 통화 시간이 정확한지 확인해야 합니다. 일련의 통화에서 유효하지 않은 통화는 포기될 수 있습니다. 예를 들어 X 동기화의 경우취소동기 Io함수가 호출되면 작업 X가 완료된 후에만 작업 Y가 시작됩니다(일반적으로 또는 오류와 함께) 작업 X를 호출한 스레드가 X에 대한 또 다른 동기 호출을 시작하는 경우 호출 취소는 이 새 작업을 취소할 수 있습니다.
  • 애플리케이션의 다른 부분(예: B. 스레드 풀 스레드) 간에 스레드가 공유될 때 동기 I/O를 취소하면 경합 상태가 발생할 수 있습니다.

취소할 수 없는 작업

취소,취소IoEx영형취소동기 Io일부 기능은 기능으로 재정의할 수 없습니다.이러한 기능 중 일부는 중지됩니다(예:ex 파일 복사함수) 대신 사용해야 합니다. 취소 지원 외에도 이러한 함수에는 작업 진행 상황을 추적하는 데 도움이 되는 콜백이 내장되어 있습니다. 다음 기능은 취소를 지원하지 않습니다.

  • 파일 복사-CopyFileEx 사용
  • 파일 이동-우산도 MoveFileWithProgress
  • MoverArchivoEx-우산도 MoveFileWithProgress
  • 파일 바꾸기

자세한 내용은완료/취소된 I/O 선언 보기.

비동기 I/O 재정의

비동기 I/O는 I/O 작업을 실행한 프로세스의 모든 스레드에서 취소할 수 있습니다. I/O가 수행된 식별자와 해당하는 경우 I/O를 수행하는 데 사용된 오버레이 구조를 지정해야 합니다. 계단식 프레임워크 또는 완료 콜백에서 반환된 상태를 검사하여 취소가 발생했는지 여부를 확인할 수 있습니다.ERROR_OPERATION_ABORTED상태는 작업이 취소되었음을 나타냅니다.

다음 예는 시간이 초과되어 읽기를 시도하는 루틴을 보여줍니다. 기한이 만료되면취소IoEx기능으로 취소하십시오.

#include <windows.h>BOOL DoCancelableRead(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout, LPBOOL pbCancelCalled) //// 매개변수://// hFile - 파일에 대한 읽기 가능한 열린 핸들 또는 장치 //// lpBuffer: 읽은 데이터를 저장할 버퍼에 대한 포인터 //// nNumberOfBytesToRead: 파일 또는 장치에서 // 읽을 바이트 수. // lpBuffer가 가리키는 버퍼의 실제 크기보다 작거나 같아야 합니다. //// lpNumberOfBytesRead: 모든 I/O가 완료되거나 취소된 후 // 읽은 바이트 수를 얻기 위한 DWORD에 대한 포인터입니다. /// lpOverlapped - // 유효한 hEvent가 있는 미리 구성된 OVERLAPPED 구조에 대한 포인터 // 호출자가 이 구조를 올바르게 초기화하지 않으면 // 이 루틴은 실패합니다. //// dwTimeout - I/O를 읽기 위해 원하는 시간 제한(밀리초)입니다.// 해당 시간이 지나면 I/O가 취소됩니다.// // pbCancelCalled - 호출자에게 이 / / 루틴이 I/O 중단을 수행하려고 했습니다.//// 반환 값://// 성공 시 TRUE, 오류 시 FALSE.//{ BOOL 결과; DWORD 대기 타이머; BOOL bioCompletion = FALSE; const DWORD PollInterval = 100; // 밀리초 // "Out" 매개변수 초기화 *pbCancelCalled = FALSE; *lpNumberOfBytesRead = 0; // I/O, 이 경우에는 읽기 작업입니다. 결과 = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); if (result == FALSE) { if (GetLastError() != ERROR_IO_PENDING) { // 함수 호출이 실패했습니다. ToDo: 오류 로그 및 복구. 거짓 반환; } } else { // I/O 완료, 리스트. TRUE를 반환합니다. } // I/O가 대기 중이므로 호출 시간이 초과될 때까지 기다립니다. // 그렇다면 CancelIoEx 함수로 I/O를 취소한다. for (waitTimer = 0; waitTimer < dwTimeout; waitTimer += PollInterval) { 결과 = GetOverlappedResult(hFile, lpOverlapped, lpNumberOfBytesRead, FALSE); if (result == FALSE) { if (GetLastError() != ERROR_IO_PENDING) { // 함수 호출이 실패했습니다. ToDo: 오류 로그 및 복구. 거짓 반환; } 일시 중지(PollInterval); } else { bIoComplete = TRUE; 부수다; } } if (bIoComplete == FALSE) { result = CancelIoEx( hFile, lpOverlapped ); *pbCancelCalled = 참; if (result == TRUE || GetLastError() != ERROR_NOT_FOUND) { // I/O 하위 시스템이 취소를 확인할 때까지 기다립니다. // 호출 타이밍에 따라 I/O가 // 취소 상태로 완료되거나 정상적으로 완료될 수 있습니다(ReadFile이 // CancelIoEx가 호출된 시점에서 // 방금 완료되었거나 // 장치가 // 취소)를 지원합니다. // 이 호출은 bWait 매개변수에 대해 TRUE를 지정합니다. 이 매개변수는 // I/O가 완료되거나 중단될 때까지 차단하여 기본 장치 드라이버 및 관련 하드웨어가 // 올바르게 작동하는 한 // 실행을 계속할 수 있도록 합니다. 드라이버에 문제가 있는 경우 // 여기에서 응답을 중지하는 것이 문제를 계속 숨기려고 시도하는 것보다 낫습니다. 결과 = GetOverlappedResult(hFile, lpOverlapped, lpNumberOfBytesRead, TRUE); // ToDo: 결과를 확인하고 오류를 기록합니다. } } 결과를 반환합니다.}

동기 I/O 오버레이

동기 I/O는 I/O 작업을 실행한 프로세스의 모든 스레드에 의해 중단될 수 있습니다. 현재 I/O 작업을 수행 중인 스레드에 대한 핸들을 제공해야 합니다.

다음 예에서는 두 개의 루틴을 보여줍니다.

  • 동기 IoWorker기능은파일 생성함수 호출로 시작하여 일부 동기 파일 I/O를 구현하는 작업자 스레드입니다. 루틴이 성공하면 여기에 포함되지 않은 루틴 뒤에 추가 작업이 있을 수 있습니다. 일반 변수완료 상태모든 작업이 성공했는지 또는 작업이 실패했는지 또는 취소되었는지 확인합니다. 일반 변수dwOperationInProgress파일 I/O가 아직 진행 중인지 여부를 나타냅니다.

    참조이 예에서 UI 스레드는 작업자 스레드도 폴링할 수 있습니다.

    여기에 포함되지 않은 추가 수동 검사는 파일 I/O 호출 사이의 짧은 시간 내에 취소가 요청되는 경우 나머지 작업이 중단되도록 합니다.동기 IoWorker역할에 필요합니다.

  • MainUIThreadMessageHandler이 함수는 UI 스레드의 창 프로시저에서 메시지 처리기를 시뮬레이트합니다. 사용자는 사용자 지정 창 메시지(WM_MYSYNCOPS지정된 섹션에서).Dann CreateFileThread이 함수는 새 스레드를 만듭니다. 그 다음에동기 IoWorker기능이 시작됩니다. 작업자 스레드가 요청된 I/O를 수행하는 동안 UI 스레드는 메시지를 계속 처리합니다. 사용자가 완료되지 않은 작업을 취소하기로 결정한 경우(일반적으로 취소 버튼 클릭)루틴(WM_MYCANCEL표시된 섹션에서).CreateFileThread함수에서 반환된 스레드 ID 사용취소동기 Io함수를 호출합니다.취소동기 Io함수는 취소 시도 직후에 반환됩니다. 마지막으로 사용자 또는 응용 프로그램은 파일 작업이 완료되었는지 여부에 따라 이후에 다른 작업을 요청할 수 있습니다. 이 경우 루틴(WM_PROCESSDATA섹션) 먼저 작업이 완료되었는지 확인한 다음 정리 작업을 수행합니다.

    참조이 예에서 취소는 작업 순서의 어느 곳에서나 발생할 수 있으므로 호출자는 계속하기 전에 상태가 일관되거나 최소한 이해되었는지 확인하려고 할 수 있습니다.

// 이 예제의 범위를 벗어나는 // 메시지 펌프에 대한 사용자 지정 코드입니다. Windows 메시지와 메시지 폭탄은 // 다른 곳에서 잘 문서화되어 있습니다. 핸들 hfile; g_dwOperationInProgress = 참; g_CompletionStatus = ERROR_SUCCESS; hFile = CreateFileA(lpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { BOOL 결과 = TRUE; // TODO: 파일 생성 성공. // 코드를 붙여넣어 hFile에 대한 동기식 호출을 더 많이 만듭니다. // 결과 변수는 여기에서 오류 플래그 역할을 해야 하지만 // 코드에 필요한 모든 것이 될 수 있습니다. if (result == FALSE) { // 작업이 실패했거나 중단되었습니다. 중단된 경우 // GetLastError()는 ERROR_OPERATION_ABORTED를 반환합니다. g_EstadoCompleto = GetLastError(); } 클로즈핸들(hFile); } else { // CreateFile이 실패했거나 중단되었습니다. 중단된 경우 // GetLastError()는 ERROR_OPERATION_ABORTED를 반환합니다. g_EstadoCompleto = GetLastError(); } g_dwOperationInProgress = FALSE;} LRESULTCALLBACKMainUIThreadMessageHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(hwnd); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); HANDLE syncThread = INVALID_HANDLE_VALUE; // 여기에 초기화를 넣습니다. switch (uMsg) { // 사용자가 파일 작업을 요청했습니다. 코드를 붙여넣어 // 매개변수의 파일 이름을 가져옵니다. 케이스 WM_MYSYNCOPS: syncThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SynchronousIoWorker, &g_lpFileName, 0, NULL); if (syncThread == INVALID_HANDLE_VALUE) { // 코드를 붙여넣어 오류를 처리합니다. } 부수다; // 사용자가 취소 버튼을 클릭했습니다. case WM_MYCANCEL: if (syncThread != INVALID_HANDLE_VALUE) { CancelSynchronousIo(syncThread); } 부수다; // 사용자가 추가 작업을 요청했습니다. case WM_PROCESSDATA: if (!g_dwOperationInProgress) { if (g_CompletionStatus == ERROR_OPERATION_ABORTED) { // 여기에 정리 코드를 입력하세요. } else { // 다른 경우를 처리하는 코드를 추가합니다. } } 부수다; }는 TRUE를 반환합니다. }

동기 및 비동기 I/O

Top Articles
Latest Posts
Article information

Author: Corie Satterfield

Last Updated: 03/23/2023

Views: 6053

Rating: 4.1 / 5 (62 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Corie Satterfield

Birthday: 1992-08-19

Address: 850 Benjamin Bridge, Dickinsonchester, CO 68572-0542

Phone: +26813599986666

Job: Sales Manager

Hobby: Table tennis, Soapmaking, Flower arranging, amateur radio, Rock climbing, scrapbook, Horseback riding

Introduction: My name is Corie Satterfield, I am a fancy, perfect, spotless, quaint, fantastic, funny, lucky person who loves writing and wants to share my knowledge and understanding with you.