본문 바로가기

C#

C# Weak Event Pattern 적용하기

이 글에서는 C#에서 메모리 누수를 방지하는 Weak Event Pattern 적용 방법을 간략하게 설명합니다. 일반 이벤트 구독 시, 구독자가 해제되지 않으면 가비지 컬렉션이 이루어지지 않아 메모리 누수가 발생할 수 있습니다. 이를 해결하는 패턴이 바로 Weak Event Pattern입니다.

1. Weak Event Pattern 기본 개념

Weak Event Pattern은 이벤트 구독 시 강한 참조를 약한 참조(WeakReference)로 변경하여, 구독자가 가비지 컬렉션의 대상이 되도록 돕습니다. 일반 이벤트와 달리 수신자 객체가 해제될 때 자동으로 구독이 해제되어 메모리 누수를 방지합니다.

2. 구현 예제

아래는 간단한 Weak Event Pattern 구현 예제입니다.

using System;
using System.Collections.Generic;

public class WeakEventHandler where TEventArgs : EventArgs
{
    private readonly List handlers = new List();

    public void Subscribe(EventHandler handler)
    {
        handlers.Add(new WeakReference(handler));
    }

    public void Unsubscribe(EventHandler handler)
    {
        handlers.RemoveAll(wr =>
        {
            var target = wr.Target as EventHandler;
            return target == null || target == handler;
        });
    }

    public void Raise(object sender, TEventArgs e)
    {
        handlers.RemoveAll(wr => !wr.IsAlive);

        foreach (WeakReference wr in handlers)
        {
            if (wr.Target is EventHandler handler)
            {
                handler(sender, e);
            }
        }
    }
}

// 사용 예
class Publisher
{
    public WeakEventHandler MyEvent = new WeakEventHandler();

    public void RaiseEvent() => MyEvent.Raise(this, EventArgs.Empty);
}

class Subscriber
{
    public void Subscribe(Publisher pub)
    {
        pub.MyEvent.Subscribe(HandleEvent);
    }

    private void HandleEvent(object sender, EventArgs e)
    {
        Console.WriteLine("이벤트 수신");
    }
}

class Program
{
    static void Main()
    {
        var pub = new Publisher();
        var sub = new Subscriber();

        sub.Subscribe(pub);
        pub.RaiseEvent(); // 이벤트 수신 출력

        sub = null; // 구독자 해제
        GC.Collect();
        GC.WaitForPendingFinalizers();

        pub.RaiseEvent(); // 이벤트가 호출되지 않음
    }
}

3. 요약

C#에서 Weak Event Pattern을 적용하면 이벤트 수신자에 대한 강한 참조를 줄여 메모리 누수를 방지할 수 있습니다. 위 예제처럼 약한 참조를 관리하며 구독자 객체가 정상적으로 해제될 수 있게 합니다.