AutoResetEvent? ManualResetEvent? 뭐가 다를까?

안녕하세요. Windows Azure MVP 남정현입니다. 이번에 살펴볼 내용은 비동기 프로그래밍에서 중요한 컨셉 중 하나인 스레드 동기화에 약방의 감초처럼 쓰이는 AutoResetEvent와 ManualResetEvent에 대해 간단한 포스팅을 준비해보았습니다. 알아두시면 유용하게 활용할 수 있을 것입니다.

StackOverflow에 있는 글을 읽어보다 재미있는 내용이 있어서 Facebook에도 포스팅을 했었습니다.

정말 알기쉽고 명료하게 비유한 글이군요. ManualResetEvent는 수동문이고 AutoResetEvent는 지하철 개찰구 내지는 자동문과 같지요. 🙂

Yes. It’s like the difference between a tollbooth and a door. The ManualResetEvent is the door, which needs to be closed (reset). The AutoResetEvent is a tollbooth, allowing one car to go by and automatically closing before the next one can get through.

출처: http://stackoverflow.com/questions/153877/what-is-the-difference-between-manualresetevent-and-autoresetevent-in-net

그런데 정말로 그런지 알아보고 싶어서 샘플 코드를 멋대로 만들어보았습니다. 다중 스레드나 이런게 아니라 그냥 단일 스레드 상에서도 차이점이 나타나는지 알아보고 싶었는데, 확실히 특징이 보였습니다. 아래의 샘플 코드가 그렇습니다.

[#M_더보기|접기|

using System;

using System.Threading;

static class Program

{

    static void Main(string[] args)

    {

        Console.Write(“[A]utoResetEvent or [M]anualResetEvent, which one? “);

        EventWaitHandle waitHandle = null;

        switch (Char.ToLower(Console.ReadKey().KeyChar))

        {

            case ‘a’:

                waitHandle = new AutoResetEvent(false);

                break;

            case ‘m’:

                waitHandle = new ManualResetEvent(false);

                break;

            default:

                waitHandle = null;

                break;

        }

        if (waitHandle == null)

            return;

        Console.WriteLine();

        waitHandle.Set();

        Console.WriteLine(“Set”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Set”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Set”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Set”);

        waitHandle.WaitOne(1000);

        waitHandle.Reset();

        Console.WriteLine(“Reset”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Reset”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Reset”);

        waitHandle.WaitOne(1000);

        Console.WriteLine(“Reset”);

        waitHandle.WaitOne(1000);

    }

}

_M#]

키보드의 M키를 눌러서 시작하면 ManualResetEvent를 사용하여 로직을 실행하는데, 이러한 경우 처음에 Set Flag가 켜진 상태 (Set 호출)에서 WaitOne 메서드를 4번 호출하게 되는데 Flag가 켜진 상태이므로 대기하지 않고 매번 호출이 빠져 나가게 됩니다. 그러나 Reset을 호출하여 Set Flag를 끈 상태에서는 WaitOne 메서드에 지정한 대기 시간만큼 실제로 대기하게됩니다.

반면 AutoResetEvent는 Set을 처음 한번 호출했을 때만 WaitOne 메서드가 무시되고 그다음부터는 계속 WaitOne 메서드에 지정한 대기 시간만큼 실제로 대기하게 됩니다. 앞서 설명했던 것 처럼 Set 메서드를 부르고 나서 이후에 벌어지는 일에 차이가 있는 셈입니다.

AutoResetEvent의 Auto란 즉, 자동으로 Reset을 호출한다는 의미이므로 비유에서처럼 톨 부스, 지하철 개찰구같은 아날로지에 대응이 가능한 것이고, ManualResetEvent의 Manual이란 방문을 열어놓고 직접 밀어서 닫지 않는 한 문이 계속 열려있는 상태의 아날로지에 대응이 가능한 것입니다.

댓글 남기기