Microsoft MVP성태의 닷넷 이야기
교재 689, 690쪽(async/await) 질문입니다. [링크 복사], [링크+제목 복사]
조회: 4680
글쓴 사람
한예지 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/") 서비스가 중단되었습니다. ^^ (게다가 국내에서는 마땅한 기부 링크가 없습니다.)
정성태

... 16  17  18  19  20  21  22  23  24  25  26  27  28  [29]  30  ...
NoWriterDateCnt.TitleFile(s)
5155세퉁5/7/201910368관리자 권한으로 실행 시 알림창(?) 없이 바로 실행 시킬 수 있는 방법이 있을까요?? [2]파일 다운로드1
5154Soul...5/4/20197257NamedPipe 질문드립니다. [2]
5153개태5/4/20198204WCF RESTful Service에서 enum을 parameter로 쓰는방법 [2]
5152세퉁5/3/20199332인터넷 시간을 불러와 pc에 적용 시키고 싶습니다. [3]파일 다운로드1
5151이대희5/3/20197447C# 7.3으로 개정판 출간 계획이 있으신가요? [1]
5150김이현5/2/20198809C# 딕셔너리 생성에 대해 질문드립니다. [1]
5149민성5/1/20197077ftp 이미지 업로드중 [1]
5148wpf질문4/30/20197436특정 사이트를 wpf에서 popup을 항상 허용하게 할려면 어떻게 해야할까요? [5]
5147민성4/30/20196466wpf에서 작업관리자를 띠울려면 어떻게 해야 하나요? [1]
5146불파겐4/25/20196514하나의 필드를 여러 스레드에서 읽어갈 때 스레드 동기화를 하지 않으면 문제가 생길까요? [2]
5145e구름4/17/20199476Properties.Setting.Default값에 대해 질문드립니다. [2]
5144성태님 ...4/17/20196725질문하시기 전에 10000 페이지 오류 납니다. [1]
5143헌이4/16/20197646윈도우 작업표시줄에 프로그램 띄우기 [2]파일 다운로드1
5142cab2...4/9/201913227C#으로 만든 DLL 배포하기 [10]
5141하늘사랑4/5/20198092Axinterop 래퍼에 관해서 질문드립니다. [7]
5140게스트4/1/20197727안녕하세요. 초보 개발자입니다. SD리더기에서 SD카드를 꽂으면 발생하는 이벤트 문의 [2]
5139김이현3/28/201910939C#에서 CRON 같은 스케줄러를 사용하려면 어떻게 해야 하나요? [3]
5138김지원3/22/20198563유니티 쉐이더에서 오로지 포워드 애드 패스로만 만들 수 있을까요? [1]
5137세퉁3/22/201910500wpf 쓰레드에 대해 질문 있습니다. [4]
5136KGY3/13/20197171안녕하세요 닷넷코어 콘솔 프로그램 관련 질문입니다. [1]
5135러쎌3/13/20197619ASP.NET 공부 관련해서 문의를 드립니다. [1]
5134이정호3/12/20197021SampleProfiler 예제를 이용한 Class 객체의 접근 문의 [1]파일 다운로드1
5133ㅇㅇ3/12/20197924멀티코어사용 방법에 궁금한것이 있습니다. [3]
5132존기미3/3/20198159Physical Disk Access문의 [1]
5131강용규2/25/20197266c# 개발자입니다. 타이머 질문드립니다. [1]
5130노인코래방2/25/201910797C#에서 가장 좋은 성능을 보이는 파일 읽고 쓰는 방법이 무엇인가요? [2]
... 16  17  18  19  20  21  22  23  24  25  26  27  28  [29]  30  ...