방프리

24.04.24 Chapter4. 병렬 처리 (Item 42) 본문

C#/More Effective C#

24.04.24 Chapter4. 병렬 처리 (Item 42)

방프리 2024. 4. 24. 23:29

Item 42 : 잠김 영역에서는 외부 코드 호출을 삼가라

lock을 통해 보호하는 영역 내에서 리스너를 통해 함수를 호출하는 방식은 교착상태를 불러 일으킬 수 있다.

public class WorkerClass
{
    public event EventHandler<EventArgs> RaiseProgress;
    private object syncHandle = new object();
    public void DoWork()
    {
        for (int count = 0; count < 100; count++)
        {
            lock (syncHandle)
            {
                System.Threading.Thread.Sleep(100);
                progressCounter++;
                RaiseProgress?.Invoke(this, EvenrArgs.Empty);
            }
        }
    }
    
    private int progressCounter = 0;
    public int Progress
    {
        get 
        {
            lock (syncHandle)
                return progressCounter;
        }
    }
}

// 이벤트 핸들러 코드
static void engine_RaiseProgress(object sender, EventArgs e)
{
    WorkerClass engine = sender as WorkerClass;
    if (engine != null)
        Console.WriteLine(engine.Progress);
}

위와 같이 코드를 작성하였을 때 Progress 객체에 접근할 때와 engine_RaiseProgress 함수를 호출할 때 교착상태가 발생할 확률이 매우 크다. 
이 문제는 아래와 같이 수정하여 회피하는 것이 좋다.

public void DoWork()
{
    for (int count = 0; count < 100; count++)
    {
        lock (syncHandle)
        {
            System.Threading.Thread.Sleep(100);
            progressCounter++;
        }
        RaiseProgress?.Invoke(this, EvenrArgs.Empty);
    }
}
Comments