Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 3개 있습니다.)
.NET Framework: 830. C# - 비동기 호출을 취소하는 CancellationToken의 간단한 예제 코드
; https://www.sysnet.pe.kr/2/0/11888

닷넷: 2218. C# - (예를 들어, Socket) 비동기 I/O에 대한 await 호출 시 CancellationToken을 이용한 취소
; https://www.sysnet.pe.kr/2/0/13561

닷넷: 2231. C# - ReceiveTimeout, SendTimeout이 적용되지 않는 Socket await 비동기 호출
; https://www.sysnet.pe.kr/2/0/13580




C# - ReceiveTimeout, SendTimeout이 적용되지 않는 Socket await 비동기 호출

예전 글에서,

C# - (예를 들어, Socket) 비동기 I/O에 대한 await 호출 시 CancellationToken을 이용한 취소
; https://www.sysnet.pe.kr/2/0/13561

.NET Framework 환경의 NetworkStream.WriteAsync 비동기 메서드가 CancellationToken에 반응하지 않는다고 했는데요, 이 문제는 NetworkStream.ReadAsync 메서드에서도 그대로 나타납니다.

Socket clntSocket = socket.Accept();
NetworkStream ns = new NetworkStream(clntSocket);
while (true)
{
    byte [] buffer = new byte[1024];
    Console.WriteLine("Receive [before]");
    CancellationTokenSource cts = new CancellationTokenSource(3000);
    int received = await ns.ReadAsync(buffer, 0, buffer.Length, cts.Token);
    Console.WriteLine("Receive [after]");
}

위와 같이 실행하면, (클라이언트가 데이터를 전송하지 않는다고 가정하고) ns.ReadAsync는 3초 후에도 작업을 취소하지 못하고 await 콜백을 영원히 이어나가지 못합니다.




이 외에도 NetworkStream은 Socket.ReceiveTimeout, Socket.SendTimeout에도 영향을 받지 않습니다. 이전 글"에서 (.NET Framework에서 구현한) NetworkStream의 ...Async 메서드는 내부적으로 APM(Begin/End...) 비동기 메서드 호출을 사용한다고 했는데요, 이로 인해 Socket의 timeout 설정들이 적용되지 않는 것입니다.

그러니까 그냥 .NET Framework 환경에서 NetworkStream으로 비동기를 호출했을 때 timeout을 지정하는 것은 그냥 포기해야 합니다. (대신 우회 방법으로.)

또한 Socket 타입에서도 SendAsync, ReceiveAsync가 제공되는데 이것 역시 SendTimeout, ReceiveTimeout에 영향을 받지 않습니다.

clntSocket.ReceiveTimeout = 3000;

byte[] buffer = new byte[1024];
ArraySegment<byte> seg = new ArraySegment<byte>(buffer);

await clntSocket.ReceiveAsync(seg, SocketFlags.None); // 3초 지나도 await 이후의 콜백으로 진행하지 못함
            // 참고로, (.NET Framework에서 구현한) Socket 타입의 SendAsync, ReceiveAsync는 CancellationToken 인자를 아예 받지 않습니다.

사실 마이크로소프트의 문서에서도 이에 대해 명시를 하고 있습니다.

Socket.ReceiveTimeout Property
; https://learn.microsoft.com/ko-kr/dotnet/api/system.net.sockets.socket.receivetimeout

Gets or sets a value that specifies the amount of time after which a synchronous Receive call will time out.

Socket.SendTimeout Property
; https://learn.microsoft.com/ko-kr/dotnet/api/system.net.sockets.socket.sendtimeout

Gets or sets a value that specifies the amount of time after which a synchronous Send call will time out.





그렇다면 .NET Core/5+ 환경은 어떨까요? 마찬가지로 Socket 타입의 경우 SendAsync, ReceiveAsync는 SendTimeout, ReceiveTimeout에 영향을 받지 않습니다.

clntSocket.ReceiveTimeout = 3000;

byte[] buffer = new byte[1024];
ArraySegment<byte> seg = new ArraySegment<byte>(buffer);

await clntSocket.ReceiveAsync(seg, SocketFlags.None); // 3초 지나도 await 이후의 콜백으로 진행하지 못함

하지만, .NET Framework과는 달리 CancellationToken을 받는 메서드를 제공하고 있으며,

Memory<byte> seg = new Memory<byte>(buffer);
CancellationTokenSource cts = new CancellationTokenSource(3000);

await clntSocket.ReceiveAsync(seg, cts.Token); // 3초 후에 "System.OperationCanceledException: The operation was canceled." 예외 발생

Memory<byte> seg = new Memory<byte>(buffer);
CancellationTokenSource cts = new CancellationTokenSource(3000);

await clntSocket.SendAsync(seg, cts.Token); // 3초 후에 "System.OperationCanceledException: The operation was canceled." 예외 발생

Cancel 동작이 잘 수행됩니다. 그러니까 .NET Core/5+는 비동기 환경의 경우 (NetworkStream에서와 동일하게) CancellationToken으로 일관성있게 timeout 처리를 제공하고 있는 것입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 3/18/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 61  62  63  64  65  66  67  68  69  70  71  72  73  [74]  75  ...
NoWriterDateCnt.TitleFile(s)
11805정성태1/28/201914225.NET Framework: 806. C# - int []와 object []의 차이로 이해하는 제네릭의 필요성 [4]파일 다운로드1
11804정성태1/24/201912244Windows: 155. diskpart - remove letter 이후 재부팅 시 다시 드라이브 문자가 할당되는 경우
11803정성태1/10/201911721디버깅 기술: 121. windbg - 닷넷 Finalizer 스레드가 멈춰있는 현상
11802정성태1/7/201913180.NET Framework: 805. 두 개의 윈도우를 각각 실행하는 방법(Windows Forms, WPF)파일 다운로드1
11801정성태1/1/201914175개발 환경 구성: 427. Netsh의 네트워크 모니터링 기능 [3]
11800정성태12/28/201813522오류 유형: 509. WCF 호출 오류 메시지 - System.ServiceModel.CommunicationException: Internal Server Error
11799정성태12/19/201814324.NET Framework: 804. WPF(또는 WinForm)에서 UWP UI 구성 요소 사용하는 방법 [3]파일 다운로드1
11798정성태12/19/201813587개발 환경 구성: 426. vcpkg - "Building vcpkg.exe failed. Please ensure you have installed Visual Studio with the Desktop C++ workload and the Windows SDK for Desktop C++"
11797정성태12/19/201810860개발 환경 구성: 425. vcpkg - CMake Error: Problem with archive_write_header(): Can't create '' 빌드 오류
11796정성태12/19/201810513개발 환경 구성: 424. vcpkg - "File does not have expected hash" 오류를 무시하는 방법
11795정성태12/19/201812980Windows: 154. PowerShell - Zone 별로 DNS 레코드 유형 정보 조회 [1]
11794정성태12/16/201810249오류 유형: 508. Get-AzureWebsite : Request to a downlevel service failed.
11793정성태12/16/201811936개발 환경 구성: 423. NuGet 패키지 제작 - Native와 Managed DLL을 분리하는 방법 [1]
11792정성태12/11/201812624Graphics: 34. .NET으로 구현하는 OpenGL (11) - Per-Pixel Lighting파일 다운로드1
11791정성태12/11/201812666VS.NET IDE: 130. C/C++ 프로젝트의 시작 프로그램으로 .NET Core EXE를 지정하는 경우 닷넷 디버깅이 안 되는 문제 [1]
11790정성태12/11/201810967오류 유형: 507. Could not save daemon configuration to C:\ProgramData\Docker\config\daemon.json: Access to the path 'C:\ProgramData\Docker\config' is denied.
11789정성태12/10/201820948Windows: 153. C# - USB 장치의 연결 및 해제 알림을 위한 WM_DEVICECHANGE 메시지 처리 [2]파일 다운로드2
11788정성태12/4/201810826오류 유형: 506. SqlClient - Value was either too large or too small for an Int32.Couldn't store <2151292191> in ... Column
11787정성태11/29/201814899Graphics: 33. .NET으로 구현하는 OpenGL (9), (10) - OBJ File Format, Loading 3D Models파일 다운로드1
11786정성태11/29/201811502오류 유형: 505. OpenGL.NET 예제 실행 시 "Managed Debugging Assistant 'CallbackOnCollectedDelegate'" 예외 발생
11785정성태11/21/201813908디버깅 기술: 120. windbg 분석 사례 - ODP.NET 사용 시 Finalizer에서 System.AccessViolationException 예외 발생으로 인한 비정상 종료
11784정성태11/18/201813623Graphics: 32. .NET으로 구현하는 OpenGL (7), (8) - Matrices and Uniform Variables, Model, View & Projection Matrices파일 다운로드1
11783정성태11/18/201811694오류 유형: 504. 윈도우 환경에서 docker가 설치된 컴퓨터 간의 ping IP 주소 풀이 오류
11782정성태11/18/201811470Windows: 152. 윈도우 10에서 사라진 "Adapters and Bindings" 네트워크 우선순위 조정 기능 - 두 번째 이야기
11781정성태11/17/201813689개발 환경 구성: 422. SFML.NET 라이브러리 설정 방법 [1]파일 다운로드1
11780정성태11/17/201815208오류 유형: 503. vcpkg install bzip2 빌드 에러 - "Error: Building package bzip2:x86-windows failed with: BUILD_FAILED"
... 61  62  63  64  65  66  67  68  69  70  71  72  73  [74]  75  ...