방프리

24.05.27 C# 동시성 프로그래밍 (스케줄링) 본문

C#/동시성 처리

24.05.27 C# 동시성 프로그래밍 (스케줄링)

방프리 2024. 5. 27. 22:02

1. 스레드 풀에 작업 스케줄링

Task.Run을 사용하여 작업을 실행시킨다. 여러 기능이 있으나 Task.Run을 사용하는 것이 유지보수나 변경에 쉽다.

Task<int> task = Task.Run(async () =>
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    return 13;
});

 

2. 작업 스케줄러를 사용해서 코드 실행

TaskScheduler 중 TaskScheduler.Default는 작업을 스레드 풀의 큐에 넣는다. Task.Run, 병렬 처리, 데이터 흐름 코드는 모두 TaskScheduler.Default를 사용한다. TaskScheduler.FromCurrentSynchronizationContext를 사용해서 컨텍스트를 저장해놓고 나중에 다시 이 컨텍스트에 작업을 스케줄링할 수 있다.

이외에 ConcurrentExclusiveSchedulerPair라는 형식이 있는데 ExclusiveScheduler에 실행 중인 작업이 없을 때 여러 작업을 동시에 실행할 수 있는 스케줄러이다. 하지만 TaskScheduler는 플랫폼에 종속되어 사용될 수 있으니 가급적이면 사용하지 않는 것이 좋다.

 

3. 병렬 코드의 스케줄링

TaskScheduler 인스턴스를 생성한 후 Parallel 메서드에 전달할 옵션에 포함할 수 있다.
PLINQ에는 전달할 방법은 없다.

void RotateMatrices(IEnumerable<IEnumerable<Matrix>> collections, float degrees)
{
    var schedulerPair = new ConcurrentExclusiveSchedulerPair(
        TaskScheduler.Default, maxConcurrencyLevel: 8);
    TaskScheduler scheduler = schedulerPair.ConcurrentScheduler;
    ParallelOptions options = new ParallelOptions { TaskScheduler = scheduler };
    Parallel.ForEach(collections, options
        matrices => Parallel.ForEach(matrices, options,
            matrix => matrix.Rotate(degrees));
}

 

4. 스케줄러로 데이터 흐름 동기화

TaskScheduler 인스턴스를 만들고 나면 데이터 흐름 블록에 전달할 옵션에 포함할 수 있다. 

var options = new ExcutionDataflowBlockOptions
{
    TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(),
};
var multiplyBlock = new TransformBlock<int, int>(item => item * 2);
var displayBlock = new ActionBlock<int>(
    result => ListBox.Items.Add(result), options);
multiplyBlock.LinkTo(displayBlock);
Comments