• 카테고리

    질문 & 답변
  • 세부 분야

    데스크톱 앱 개발

  • 해결 여부

    해결됨

비동기 Callback방식 코드 질문

23.12.29 20:32 작성 조회수 146

1

#include <iostream>

#include <windows.h>

#include <stdio.h>

#include <tchar.h>

 

void CALLBACK FileIoComplete(

DWORD dwError,

DWORD dwTransferred,

LPOVERLAPPED pO1)

{

printf("FileIoComplete() Callback - [%d 바이트] 쓰기 완료 -%s\n", dwTransferred, (char*)pO1->hEvent);

//hEvent 멤버를 포인터로 전용했으므로 가리키는 대상 메모리를 해제한다.

//이 메모리는 IoThreadFunction() 함수에서 동적 할당된 것들이다!

delete[](char*)pO1->hEvent;

delete pO1;

puts("FileIoComplete() - return \n");

}

DWORD WINAPI IoThreadFunction(LPVOID pParam) {

//메모리를 할당하고 값을 채운다.

//이 메모리는 완료 함수에서 해제한다.

 

char* pszBuffer = new char[16];

memset(pszBuffer, 0, sizeof(char) * 16);

strcpy_s(pszBuffer, sizeof(char) * 16, "Hello IOCP");

// Allocate and initialize the OVERLAPPED structure.

 

//OVERLAPPED 구조체의 hEvent 멤버를 포인터 변수로 전용한다!

LPOVERLAPPED pOverlapped = NULL;

pOverlapped = new OVERLAPPED;

memset(pOverlapped, NULL, sizeof(OVERLAPPED));

pOverlapped->Offset = 1024 * 1024; //일부러 사이즈 작게 했습니다.

pOverlapped->hEvent = pszBuffer;

//pOverlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Manual-reset event

//비동기 쓰기를 시도한다.

//쓰기가 완료되면 완료 함수가 역호출된다.

puts("IoThreadFunction() - 중첩된 쓰기 시도");

::WriteFileEx((HANDLE)pParam, pszBuffer, sizeof(char) * 16, pOverlapped, FileIoComplete); // 함수의 주소를 쓸 수 있다.

for (; ::SleepEx(1, TRUE) != WAIT_IO_COMPLETION;); {

//SleepEx를 호출한 WorkerThread가 ALERTABLE_WAIT 상태가 된다/

puts("IothreadFunction() - return ");

}

return 0;

}

int tmain(int argc, TCHAR* argv[]) {

HANDLE hFile = ::CreateFile(_T("TestFile.txt"),

GENERIC_READ, //쓰기 모드

0, //공유 하지 않음

NULL,

CREATE_ALWAYS, //무조건 생성

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //중첩된 쓰기->비동기 쓰기

NULL);

HANDLE hThread = NULL;

DWORD dwThreadID = 0;

hThread = ::CreateThread(

NULL,

0,

IoThreadFunction,

hFile,

0,

&dwThreadID);

WaitForSingleObject(hThread, INFINITE);

}

강사님 위와 같이 코드를 작성해서 비동기 call back 방식으로 시도하려고 하는데, Hello IOCP가 쓰여지지 않고 종료도 되지 않는데, 뭔가 오류가 있는 부분이 있나요? 또, 자동으로 종료도 되었으면 하는데, 가능한가요? 어떻게 수정하면 좋을까요?

혹시 예제 코드를 공유할 수 있다면 가능한가요? 감사합니다.

답변 4

·

답변을 작성해보세요.

1

메일 확인했습니다. 보내준 압축파일에는 GENERIC_WRITE로 수정이 되어 있군요. 당연히 성공해야 할 함수가 에러가 발생할 때는 ::GetLastError() 함수를 활용해보시기 바랍니다. 에러를 쉽게 찾을 수 있습니다. 참고하시기 바랍니다. 😄

0

이렇게 봐서는 저도 답변하기가 어렵습니다. 작성한 예제 프로젝트 파일을 압축해 메일로 보내주세요. 확인해보고 메일로 회신하겠습니다. :)

jeonsh95님의 프로필

jeonsh95

2023.12.31

메일로 보냈습니다. 감사합니다.

GENERIC_WRITE로 해야 되는데, GENERIC_READ를 해서 문제가 있었던 것 같습니다.

0

jeonsh95님의 프로필

jeonsh95

2023.12.29

#include <iostream>

#include <windows.h>

#include <tchar.h>

void CALLBACK FileIoComplete(

DWORD dwError,

DWORD dwTransfered,

LPOVERLAPPED pO1)

{

printf("FileIoComplete() Callback - [%d 바이트] 쓰기 완료 -%s\n", dwTransfered, (char*)pO1->hEvent);

//hEvent 멤버를 포인터로 전용했으므로 가리키는 대상 메모리를 해제한다.

//이 메모리는 IoThreadFunction() 함수에서 동적 할당된 것들이다!

delete[] pO1->hEvent;

delete pO1;

puts("FileIoComplete() - return \n");

}

DWORD WINAPI IoThreadFunction(LPVOID pParam) {

char* pszBuffer = new char[16];

memset(pszBuffer, 0, sizeof(char) * 16);

strcpy_s(pszBuffer, sizeof(char) * 16, "Hello IOCP");

LPOVERLAPPED pOverlapped = NULL;

pOverlapped = new OVERLAPPED;

memset(pOverlapped, 0, sizeof(OVERLAPPED));

pOverlapped->Offset = 1024 1024 5;

pOverlapped->hEvent = pszBuffer;

puts("IoThreadFunction() - 중첩된 쓰기 시도");

::WriteFileEx((HANDLE)pParam,

pszBuffer,

sizeof(char) * 16,

pOverlapped,

FileIoComplete);

// 비동기 쓰기 시도에 대해 ALERTABLE_WAIT 상태로 대기

for (; ::SleepEx(1, TRUE) != WAIT_IO_COMPLETION;); {

//SleepEx를 호출한 WorkerThread가 ALERTABLE_WAIT 상태가 된다/

puts("IothreadFunction() - return ");

}

return 0;

}

int tmain(int argc, TCHAR* argv[]) {

HANDLE hFile = ::CreateFile(_T("TestFile.txt"),

GENERIC_WRITE, // 쓰기 모드

0, // 공유하지 않음

NULL,

CREATE_ALWAYS, // 무조건 생성

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // 중첩된 쓰기 -> 비동기 쓰기

NULL);

HANDLE hThread = NULL;

DWORD dwThreadID = 0;

dwThreadID=0;

hThread = ::CreateThread(

NULL,

0,

IoThreadFunction,

hFile,

0,

&dwThreadID);

//작업자 스레드가 종료될 때까지 기다린다.

::WaitForSingleObject(hThread,INFINITE);

return 0;

}

이렇게 작성해서 해결했습니다.. 감사합니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.12.29

안녕하세요, 인프런 AI 인턴입니다.

비동기 Callback 방식을 사용한 코드에 대해 질문하셨군요. 강의 중 ‘Callback 기반 비동기 파일 입/출력’ 부분에서 관련 내용을 다루고 있습니다. 아래 링크에서 유사한 질문과 강사님의 답변을 확인하실 수 있습니다. 해당 답변이 도움이 될 것 같습니다.

답변을 통해 비동기 파일 I/O 처리에 대한 이해를 높이실 수 있을 것입니다. 링크를 클릭하여 강사님의 답변을 확인해 보시길 바랍니다.