-
C# Channel프로그래밍/기록, 개념, 용어 2022. 10. 28. 14:04반응형
Channel은 Producer, Consumer 간에 데이터를 비동기적으로 스레드 세이프 하게 전달하기 위한 클래스로, 서로 다른 스레드 간에 데이터를 주고받을 때 유용합니다.
https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.channels.channel?view=net-6.0
ConcurrentQueue와의 차이점
ConcurrentQueue는 스레드 세이프한 FIFO 컨테이너이며, ConcurrentQueue와 Channel은 유사하게 보입니다.
그러나 Channel은 입력이 있을 때까지 읽기 스레드를 대기 시키는 등 데이터 전달이라는 목적에 유용한, 추가적인 기능들이 있습니다.
의사 코드로 보자면, Channel의 간단한 구현체는 아래처럼 생각할 수 있습니다.
class Channel<T> { private ConcurrentQueue<T> _queue; private Semaphore _semaphore; public void Write(T value) { _queue.Enqueue(value); // value 저장. _semaphore.Release(); // Read 하고 있는 스레드 하나를 깨움. } public async Task<T> Read() { await _semaphore.WaitAsync(); T value = _queue.Dequeue(); return value; } }
위 의사 코드는 읽기 시 무조건 대기의 예를 들었지만, 실제 Channel의 구현엔 대기를 하지 않고 읽기 시도를 하는 TryRead 메소드도 있습니다.
Channel의 사용
Channel 생성
Channel의 생성은 Channel의 static 메소드인 CreateBounded 또는 CreateUnbounded 이용합니다.
CreateBounded로 생성하는 Channel은 최대 큐잉될 수 있는 데이터의 개수를 제한하고, UnboundedChannel은 최대 데이터 개수에 제한을 두지 않습니다.
var boundedChannel = Channel.CreateBounded<string>(1000); var unboundedChannel = Channel.CreateUnbounded<string>();
- Channel의 큐잉 제한을 둬서 무엇을 할 수 있을까요?
- Channel에 더이상 입력을 받지 않는다거나
- 입력이 가능해 질 때 까지 스레드를 대기 시킨다거나
- 가장 최근, 또는 가장 오래된 데이터를 제거할 수도 있습니다.
이런 Channel이 가득 찼을 때의 동작은 CreateBoundedChannel의 인자인 BoundedChannelOptions을 설정하여 할 수 있습니다.
Channel에 쓰기
다음은 기본적인 Channel에 쓰는 동작인 WriteAsync 입니다.
좀 더 다양한 쓰기 기능은 Channel.Writer의 메소드들을 참고하면 됩니다.
var channel = Channel.CreateUnbounded<string>(); await channel.Writer.WriteAsync("Hello World!");
Channel에서 읽기
다음은 기본적인 Channel에서 읽는 동작인 ReadAsync 입니다.
좀 더 다양한 읽기 기능은 Channel.Reader의 메소드들을 참고하면 됩니다.
var channel = Channel.CreateUnbounded<string>(); //... string message = await channel.Reader.ReadAsync();
참고 & 관련하여 더 읽으면 좋을 글들
이 문서는 글을 작성할 당시 눈여겨 본 요소를 일부 추려 적은 것으로, 더 많은 내용은 아래 링크를 참고하면 좋습니다.
- https://learn.microsoft.com/en-us/dotnet/api/system.threading.channels.boundedchanneloptions?view=net-7.0
- https://learn.microsoft.com/ko-kr/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=net-6.0
- https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/
- https://dotnetcoretutorials.com/2020/11/24/using-channels-in-net-core-part-1-getting-started/
- https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.channels?view=net-6.0
- https://learn.microsoft.com/en-us/dotnet/core/extensions/channels
반응형'프로그래밍 > 기록, 개념, 용어' 카테고리의 다른 글
간단한 디펜던시 인젝션(DI) 구현 (0) 2022.11.14 ASP.NET CORE에서의 클레임 키 임의 변경 (0) 2022.11.04 C# - ArrayPool, MemoryPool (0) 2022.10.13 동시성 토큰 (0) 2022.10.02 gRPC Performance Best Practice의 C++ - Enable write batching in streams (0) 2022.09.27