Microsoft MVP성태의 닷넷 이야기
교재 689, 690쪽(async/await) 질문입니다. [링크 복사], [링크+제목 복사]
조회: 4666
글쓴 사람
한예지 donator
홈페이지
첨부 파일
 

선생님 안녕하세요.

https://www.sysnet.pe.kr/3/0/5314 에 글을 읽고 좀 더 명확하게 정리했봤는데
혹시 제가 잘못 해석한 부분이 있을까요?

private static async void ProcessTcpClient(TcpClient client){
    NetworkStream ns = client.GetStream();
    
    byte[] buffer = new byte[1024];
    // await 키워드를 만나면 Main 스레드는 ProcessTcpClient 메서드를 벗어난다.
    // 스레드 풀에서 가져온 A 스레드를 이용해서 작업
    // IRP(I/O 요청 패킷)을 디바이스 드라이버의 IRP 큐에 IRP를 큐잉작업까지만 스레드 A는 수행하고
    // 스레드 A는 스레드 풀에서 회수한다.
    int received = await ns.ReadAsync(buffer, 0, buffer.Length);
    // 만약 Read 작업 결과이 완료되었다면 스레드 풀에서 스레드를 꺼내서 아래 두 줄을 실행하는데
    // 이때 우연히 스레드 A를 꺼낼 수 있거나 혹은 새로운 스레드 B를 꺼낼 수 있다.
    // 하지만 여기서는 스레드 B를 통해서 아래 2줄을 수행한다고 가정한다.
    string txt = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
    byte[] sendBuffer = Encosing.UTF8.GetBytes("Hello :" + txt);
    
    // await 키워드를 만났기 때문에 이전에 수행된 스레드 B가 스레드 풀에서 회수되고
    // 스레드 풀에서 꺼낸 새로운 스레드 C를 통해 작업을 수행한다.
    // 마찬가지로 디바이스 드라이버의 IRP 큐에 IRP를 큐잉작업까지만 스레드 C는 수행하고
    // 스레드 풀에서 스레드 C를 회수한다.
    await ns.WriteAsync(sendBuffer, 0, sendBuffer.Length);
    // 스레드 Write 작업이 완료되었다면 스레드 풀에서 스레드를 꺼내서 아래 한 줄을 수행하는데
    // 이때 우연히 스레드 A 혹은 스레드 B를 꺼낼 수 있지만
    // 여기서는 스레드 D를 통해서 아래 한 줄을 수행한다고 가정한다.
    ns.Close();
}








[최초 등록일: ]
[최종 수정일: 5/9/2022]


비밀번호

댓글 작성자
 



2022-05-09 10시32분
아래와 같이 정정했으니 또 궁금하신 것이 있으면 질문해주세요.

private static async void ProcessTcpClient(TcpClient client){
    NetworkStream ns = client.GetStream();
    
    byte[] buffer = new byte[1024];
    // await 키워드를 만나면 Main 스레드는 ProcessTcpClient 메서드를 벗어난다.
       ==> 엄밀히는 그럴 수도 있고, 아닐 수도 있습니다. (await 대상이 되는 메서드가 꼭 내부적으로 비동기 작업을 한다는 보장은 없습니다. (참고: https://www.sysnet.pe.kr/2/0/11431)
       
    // 스레드 풀에서 가져온 A 스레드를 이용해서 작업
       ==> 아직 이 단계에서는 스레드 풀에서 가져온 스레드로 작업을 하지 않습니다.
       ==> ReadAsync 내부의 비동기 호출 단계까지는 "ProcessTcpClient" 메서드를 호출한 스레드가 담당합니다.

    // IRP(I/O 요청 패킷)을 디바이스 드라이버의 IRP 큐에 IRP를 큐잉 작업까지만 호출 스레드가 담당
    int received = await ns.ReadAsync(buffer, 0, buffer.Length);

    // 만약 Read 작업 결과가 완료되었다면 스레드 풀에서 스레드(예를 들어 스레드 A)를 꺼내서 아래 두 줄을 실행하는데,
    string txt = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
    byte[] sendBuffer = Encosing.UTF8.GetBytes("Hello :" + txt);
    
    // 마찬가지로 디바이스 드라이버의 IRP 큐에 IRP를 큐잉 작업까지만 스레드 A는 수행하고
    await ns.WriteAsync(sendBuffer, 0, sendBuffer.Length);
    // 스레드 Write 작업이 완료되었다면 스레드 풀에서 스레드를 꺼내서 아래 한 줄을 수행하는데
    // 이때 우연히 스레드 A를 꺼낼 수 있지만
    // 여기서는 또다른 스레드 B를 통해서 아래 한 줄을 수행한다고 가정한다.
    ns.Close();
}
정성태
2022-05-10 01시18분
[한예지] 답변 감사드립니다!

답변해 주신 내용을 바탕으로 아래와 같이 정리해도 문제 없을까요?

private static async void ProcessTcpClient(TcpClient client){
    NetworkStream ns = client.GetStream();
    
    byte[] buffer = new byte[1024];
    // Main 스레드가 IRP(I/O 요청 패킷)을 디바이스 드라이버의 IRP 큐에 IRP를 큐잉 작업까지
    // 처리하고 ProcessTcpClient 메서드를 벗어난다.
    int received = await ns.ReadAsync(buffer, 0, buffer.Length);

    // 만약 Read 작업 결과가 완료되었다면 스레드 풀에서 스레드(스레드 A라고 가정)를 꺼내서 아래 두 줄을 실행하는데,
    string txt = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
    byte[] sendBuffer = Encosing.UTF8.GetBytes("Hello :" + txt);
    
    // 마찬가지로 디바이스 드라이버의 IRP 큐에 IRP를 큐잉 작업까지만 스레드 A는 수행하고 스레드 풀에 회수된다.
    await ns.WriteAsync(sendBuffer, 0, sendBuffer.Length);
    // 스레드 Write 작업이 완료되었다면 스레드 풀에서 스레드를 꺼내서 아래 한 줄을 수행하는데
    // 이때 우연히 스레드 A를 꺼낼 수 있지만
    // 여기서는 또 다른 스레드 B를 통해서 아래 한 줄을 수행한다고 가정한다.
    ns.Close();
}
[guest]
2022-05-10 01시34분
넵, 개념적으로 그렇게 이해하시면 좋겠습니다. (그나저나... 많은 분들이 이에 대해 혼란을 느끼시는 듯하니 관련해서 글을 하나 써야겠군요. ^^;)
정성태
2022-05-10 04시03분
[한예지] 작성해 주시면 정말 감사하죠! 기대하고 있겠습니다^^

아, 혹시 후원 채널을 1개로 하신 이유가 있으신가요??

예전에 있던 BUY ME A COFFEE 버튼은 회원가입을 안 해도 되는데

paypal은 회원가입을 해야 되네요 ㅜ_ㅜ
[guest]
2022-05-10 07시06분
아쉽게도 donaricano("https://donaricano.com/") 서비스가 중단되었습니다. ^^ (게다가 국내에서는 마땅한 기부 링크가 없습니다.)
정성태

1  [2]  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5909guest4/22/20233829Visual Studio 구매 시(1인 개발자) [4]
5908guest4/22/20233660텅빈 원그리기 [5]
5907민성4/21/20233305안녕하세요 서버 백업 문제에 대해서 [2]
5906guest4/21/20233437Dispatcher 서비스 구현 질문 [1]
5905guest4/20/20233756tabControl의 tabPage가 여러 개일 때 순서를 바꾸기가 까다롭네요 [5]
5904guest4/18/20233687[신규자료첨부] DLL 'SQLite.Interop.dll'을 찾을 수 없습니다 [4]파일 다운로드1
5903guest4/18/20233136fileSystemWatcher 이벤트 관련 질문입니다 [2]
5902guest4/17/20233772c#으로 USB 관련 질문 [2]
5901guest4/17/20233331내솔루션 판매 시 1.0.0.0 폴더와 Sqlite 배포 [5]
5900guest4/17/20234502DLL 'SQLite.Interop.dll'을 찾을 수 없습니다 [2]파일 다운로드1
5899guest4/17/20233444Dictionary와 Linq [4]
5898차가워4/17/20233256CNTK 교육 문의 [1]
5897guest4/17/20233179Socket스레드와 UI thread [4]
5896HAN4/16/20233162c언어 return 에 대해 궁금한게 있어요. [1]파일 다운로드1
5895guest4/15/20232917Drag and Drop - 모든 컨트롤 [2]
5894송부장4/14/20234325[질문] Visual Studio 2022에서 '도구 상자 항목 선택'의 'COM 구성 요소' 탭에서 ActiveX 목록이 보이지 않습니다. [3]파일 다운로드2
5893감사합니...4/14/20232915오라클 OLEDB방식 접속 후 SELECT 'TEST' TEST_VALUE FROM DUAL의 값이 이상합니다. [1]
5892한무4/14/20233100C# 으로 백그라운드에서 워드를 실행하여 매크로 실행이 가능 할까요? [2]
5891리세4/14/20233003안녕하세요.C# 서버프로그램에서의 Mysql 쿼리문제(다중쿼리 실행)에 대해 문의드립니다. [2]
5890guest4/14/20233661C# 프리랜서로 돈 벌려면 성태님 책 마스터하면 되나요? [6]
5889전예찬4/14/20232840C# 파일 복사 관련 질문 드립니다. [3]
5888정경구4/12/20233125C# 첫 환경 세팅과 관련해서 [4]
5887HAN4/12/20232752안녕하세요 파이썬도 공유 가능 할까요? [1]
5886guest4/11/20233144필요한 어셈블리만 다운로드 및 재로딩하는 방법에 관하여 [2]
5885guest4/11/20232994c#으로 드림위버같은 거 만들어볼려는데요 [6]
5884궁금이4/11/20232868부모 클래스에서 예외 발생시 힙 영역에 할당 ? [2]
1  [2]  3  4  5  6  7  8  9  10  11  12  13  14  15  ...