이벤트 처리 및 발생Handling and raising events

.NET의 이벤트는 대리자 모델을 기반으로 합니다.Events in .NET are based on the delegate model. 대리자 모델은 구독자가 공급자를 등록하고 공급자로부터 알림을 수신하는 데 사용할 수 있는 관찰자 디자인 패턴을 따릅니다.The delegate model follows the observer design pattern, which enables a subscriber to register with and receive notifications from a provider. 이벤트 전송자는 이벤트가 발생했음을 알리고, 이벤트 수신자는 해당 알림을 수신하고 그에 대한 응답을 정의합니다.An event sender pushes a notification that an event has happened, and an event receiver receives that notification and defines a response to it. 이 문서에서는 대리자 모델의 주요 구성 요소, 애플리케이션에서 이벤트를 사용하는 방법 및 코드에서 이벤트를 구현하는 방법에 대해 설명합니다.This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code.

Windows 8.x Store 앱에서의 이벤트 처리에 대한 자세한 내용은 이벤트 및 라우트된 이벤트 개요를 참조하세요.For information about handling events in Windows 8.x Store apps, see Events and routed events overview.

이벤트Events

이벤트는 개체에서 작업 실행을 알리기 위해 보내는 메시지입니다.An event is a message sent by an object to signal the occurrence of an action. 이 작업은 단추 클릭과 같은 사용자 조작으로 발생하거나, 속성 값 변경 등의 다른 프로그램 논리에서 발생할 수 있습니다.The action can be caused by user interaction, such as a button click, or it can result from some other program logic, such as changing a property’s value. 이벤트를 발생시키는 개체를 이벤트 전송자라고 하며The object that raises the event is called the event sender. 이벤트 전송자는 어떤 개체 또는 메서드가 발생되는 이벤트를 수신(처리)할지 모릅니다.The event sender doesn't know which object or method will receive (handle) the events it raises. 이벤트는 일반적으로 이벤트 전송자의 멤버입니다. 예를 들어 Click 이벤트는 Button 클래스의 멤버이고, PropertyChanged 이벤트는 INotifyPropertyChanged 인터페이스를 구현하는 클래스의 멤버입니다.The event is typically a member of the event sender; for example, the Click event is a member of the Button class, and the PropertyChanged event is a member of the class that implements the INotifyPropertyChanged interface.

이벤트를 정의하려면 C# event 또는 Visual Basic Event 키워드를 이벤트 클래스의 시그니처에서 사용하고 이벤트에 대한 대리자의 형식을 지정합니다.To define an event, you use the C# event or the Visual Basic Event keyword in the signature of your event class, and specify the type of delegate for the event. 대리자는 다음 섹션에 설명되어 있습니다.Delegates are described in the next section.

일반적으로 이벤트를 발생시키려면 protectedvirtual(C#) 또는 ProtectedOverridable(Visual Basic)이라고 표시된 메서드를 추가합니다.Typically, to raise an event, you add a method that is marked as protected and virtual (in C#) or Protected and Overridable (in Visual Basic). 이 메서드의 이름을 OnEventName으로 지정합니다(예: OnDataReceived).Name this method OnEventName; for example, OnDataReceived. 메서드에서 EventArgs 형식이나 파생 형식의 개체인 이벤트 데이터 개체를 지정하는 하나의 매개 변수를 사용해야 합니다.The method should take one parameter that specifies an event data object, which is an object of type EventArgs or a derived type. 이 메서드를 사용하면 파생된 클래스를 이용해 이벤트를 발생시키는 논리를 재정의할 수 있습니다.You provide this method to enable derived classes to override the logic for raising the event. 파생된 클래스는 등록된 대리자가 이벤트를 수신할 수 있도록 해주는 기본 클래스의 OnEventName 메서드를 항상 호출해야 합니다.A derived class should always call the OnEventName method of the base class to ensure that registered delegates receive the event.

다음 예제에서는 ThresholdReached라는 이벤트를 선언하는 방법을 보여 줍니다.The following example shows how to declare an event named ThresholdReached. 이 이벤트는 EventHandler 대리자와 연결되어 있고 OnThresholdReached라는 메서드에서 발생합니다.The event is associated with the EventHandler delegate and raised in a method named OnThresholdReached.

class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.Invoke(this, e);
    }

    // provide remaining implementation for the class
}
Public Class Counter
    Public Event ThresholdReached As EventHandler

    Protected Overridable Sub OnThresholdReached(e As EventArgs)
        RaiseEvent ThresholdReached(Me, e)
    End Sub

    ' provide remaining implementation for the class
End Class

대리자Delegates

대리자는 메서드에 대한 참조를 가지는 형식입니다.A delegate is a type that holds a reference to a method. 대리자는 참조하는 메서드의 반환 형식 및 매개 변수를 보여주는 시그니처를 사용하여 선언되며, 해당 시그니처와 일치하는 메서드에 대한 참조만 포함할 수 있습니다.A delegate is declared with a signature that shows the return type and parameters for the methods it references, and it can hold references only to methods that match its signature. 따라서 대리자는 형식이 안전한 함수 포인터나 콜백과 동일합니다.A delegate is thus equivalent to a type-safe function pointer or a callback. 대리자 선언은 대리자 클래스를 효율적으로 정의할 수 있습니다.A delegate declaration is sufficient to define a delegate class.

대리자는 .NET에서 여러 용도로 사용됩니다.Delegates have many uses in .NET. 이벤트의 컨텍스트에서 대리자는 이벤트 소스와 이벤트를 처리하는 코드 간의 매개자 (또는 포인터와 같은 메커니즘)입니다.In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. 대리자와 이벤트의 연결은 이전 섹션의 예제에서와 같이 이벤트 선언에서 대리자 형식을 포함하는 방식으로 수행됩니다.You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. 대리자에 대한 자세한 내용은 Delegate 클래스를 참조하십시오.For more information about delegates, see the Delegate class.

.NET에서는 EventHandlerEventHandler<TEventArgs> 대리자를 제공하여 대부분의 이벤트 시나리오를 지원합니다..NET provides the EventHandler and EventHandler<TEventArgs> delegates to support most event scenarios. 이벤트 데이터를 포함하지 않는 모든 이벤트에 대해 EventHandler 대리자를 사용합니다.Use the EventHandler delegate for all events that do not include event data. 이벤트에 대한 데이터를 포함하는 이벤트에 대해 EventHandler<TEventArgs> 대리자를 사용합니다.Use the EventHandler<TEventArgs> delegate for events that include data about the event. 이러한 대리자는 반환 형식 값이 없으며, 두 개의 매개 변수(이벤트 소스 개체 및 이벤트 데이터 개체)를 사용합니다.These delegates have no return type value and take two parameters (an object for the source of the event, and an object for event data).

대리자는 멀티캐스트로, 둘 이상의 이벤트 처리 메서드에 대한 참조를 포함할 수 있습니다.Delegates are multicast, which means that they can hold references to more than one event-handling method. 자세한 내용은 Delegate 참조 페이지를 참조하십시오.For details, see the Delegate reference page. 대리자를 사용하면 유연하고 정밀하게 이벤트 처리를 제어할 수 있습니다.Delegates provide flexibility and fine-grained control in event handling. 대리자는 이벤트에 등록된 이벤트 처리기의 목록을 유지 관리하여 이벤트를 발생시키는 클래스의 이벤트 발송자 이벤트로서 작동합니다.A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event.

EventHandlerEventHandler<TEventArgs> 대리자가 작동하지 않는 시나리오의 경우, 대리자를 정의할 수 있습니다.For scenarios where the EventHandler and EventHandler<TEventArgs> delegates do not work, you can define a delegate. 대리자를 정의해야 하는 시나리오(예: 제네릭을 인식할 수 없는 코드를 사용하여 작업해야 하는 경우)는 매우 드뭅니다.Scenarios that require you to define a delegate are very rare, such as when you must work with code that does not recognize generics. 선언에서 대리자는 C# delegate 및 Visual Basic Delegate 키워드를 사용하여 표시합니다.You mark a delegate with the C# delegate and Visual Basic Delegate keyword in the declaration. 다음 예제에서는 ThresholdReachedEventHandler라는 대리자를 선언하는 방법을 보여 줍니다.The following example shows how to declare a delegate named ThresholdReachedEventHandler.

public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)

이벤트 데이터Event data

이벤트와 관련된 데이터는 이벤트 데이터 클래스를 통해 제공할 수 있습니다.Data that is associated with an event can be provided through an event data class. .NET에서는 애플리케이션에 사용할 수 있는 여러 이벤트 데이터 클래스를 제공합니다..NET provides many event data classes that you can use in your applications. 예를 들어, SerialDataReceivedEventArgs 클래스는 SerialPort.DataReceived 이벤트에 대한 이벤트 데이터 클래스에 해당합니다.For example, the SerialDataReceivedEventArgs class is the event data class for the SerialPort.DataReceived event. .NET에서는 모든 이벤트 데이터 클래스를 EventArgs로 끝내는 명명 패턴을 따릅니다..NET follows a naming pattern of ending all event data classes with EventArgs. 이벤트에 대한 대리자를 보는 것만으로 어떠한 이벤트 데이터 클래스가 이벤트에 연결되어 있는지 확인할 수 있습니다.You determine which event data class is associated with an event by looking at the delegate for the event. 예를 들어, SerialDataReceivedEventHandler 대리자는 매개 변수 중 하나로 SerialDataReceivedEventArgs 클래스를 가집니다.For example, the SerialDataReceivedEventHandler delegate includes the SerialDataReceivedEventArgs class as one of its parameters.

EventArgs 클래스는 모든 이벤트 데이터 클래스의 기본 형식입니다.The EventArgs class is the base type for all event data classes. EventArgs는 이벤트에 연결된 데이터가 없을 때 사용하는 클래스이기도 합니다.EventArgs is also the class you use when an event does not have any data associated with it. 다른 클래스에게 어떤 일이 발생했으며 어떠한 데이터도 전달할 필요가 없다는 것을 알리기만 하는 이벤트를 만들려면 대리자에서 두 번째 매개 변수로 EventArgs 클래스를 포함합니다.When you create an event that is only meant to notify other classes that something happened and does not need to pass any data, include the EventArgs class as the second parameter in the delegate. 어떠한 데이터도 제공되지 않은 경우 EventArgs.Empty 값을 전달할 수 있습니다.You can pass the EventArgs.Empty value when no data is provided. EventHandler 대리자는 매개 변수로 EventArgs 클래스를 포함합니다.The EventHandler delegate includes the EventArgs class as a parameter.

사용자 지정된 이벤트 데이터 클래스를 만들려면 EventArgs로부터 파생된 클래스를 만든 후, 이벤트 관련 데이터를 전달하는 데 필요한 멤버를 제공합니다.When you want to create a customized event data class, create a class that derives from EventArgs, and then provide any members needed to pass data that is related to the event. 일반적으로 .NET과 동일한 명명 패턴을 사용하여 이벤트 데이터 클래스 이름을 EventArgs로 끝내야 합니다.Typically, you should use the same naming pattern as .NET and end your event data class name with EventArgs.

다음 예제에서는 ThresholdReachedEventArgs라는 이벤트 데이터 클래스를 보여 줍니다.The following example shows an event data class named ThresholdReachedEventArgs. 발생한 이벤트와 관련된 속성도 포함됩니다.It contains properties that are specific to the event being raised.

public class ThresholdReachedEventArgs : EventArgs
{
    public int Threshold { get; set; }
    public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
    Inherits EventArgs

    Public Property Threshold As Integer
    Public Property TimeReached As DateTime
End Class

이벤트 처리기Event handlers

이벤트에 응답하려면 이벤트 수신기에서 이벤트 처리기 메서드를 정의합니다.To respond to an event, you define an event handler method in the event receiver. 이 메서드는 처리 중인 이벤트에 대한 대리자의 시그니처와 일치해야 합니다.This method must match the signature of the delegate for the event you are handling. 이벤트 처리기에서 사용자가 단추를 클릭한 후 사용자 입력 정보를 수집하는 등의 이벤트가 발생하는 경우 필요한 작업을 수행합니다.In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user clicks a button. 이벤트가 발생할 때 알림을 받기 위해서는 이벤트 처리기 메서드에서 이벤트를 구독해야 합니다.To receive notifications when the event occurs, your event handler method must subscribe to the event.

다음 예제에서는 c_ThresholdReached 대리인에 대한 시그니처와 일치하는 EventHandler라는 이벤트 처리기 메서드를 보여 줍니다.The following example shows an event handler method named c_ThresholdReached that matches the signature for the EventHandler delegate. 이 메서드는 ThresholdReached 이벤트를 구독합니다.The method subscribes to the ThresholdReached event.

class Program
{
    static void Main()
    {
        var c = new Counter();
        c.ThresholdReached += c_ThresholdReached;

        // provide remaining implementation for the class
    }

    static void c_ThresholdReached(object sender, EventArgs e)
    {
        Console.WriteLine("The threshold was reached.");
    }
}
Module Module1

    Sub Main()
        Dim c As New Counter()
        AddHandler c.ThresholdReached, AddressOf c_ThresholdReached

        ' provide remaining implementation for the class
    End Sub

    Sub c_ThresholdReached(sender As Object, e As EventArgs)
        Console.WriteLine("The threshold was reached.")
    End Sub
End Module

정적 및 동적 이벤트 처리기Static and dynamic event handlers

.NET에서는 구독자가 정적이나 동적으로 이벤트 알림을 등록할 수 있습니다..NET allows subscribers to register for event notifications either statically or dynamically. 고정 이벤트 처리기는 해당 이벤트가 처리되는 클래스의 전체 수명 동안 적용됩니다.Static event handlers are in effect for the entire life of the class whose events they handle. 동적 이벤트 처리기는 특정 조건부 프로그램 논리에 대한 응답에서 일반적으로 프로그램을 실행하는 동안 명시적으로 활성화되고 비활성화됩니다.Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. 예를 들어 이벤트 알림이 특정 조건 하에서만 필요하거나 애플리케이션이 여러 이벤트 처리기를 제공하고 런타임 조건에서 사용할 적절한 이벤트 처리기를 정의하는 경우에 사용될 수 있습니다.For example, they can be used if event notifications are needed only under certain conditions or if an application provides multiple event handlers and run-time conditions define the appropriate one to use. 이전 섹션의 예제에서는 이벤트 처리기를 동적으로 추가하는 방법을 보여 줍니다.The example in the previous section shows how to dynamically add an event handler. 자세한 내용은 이벤트(Visual Basic의 경우) 및 이벤트(C#의 경우)를 참조하세요.For more information, see Events (in Visual Basic) and Events (in C#).

여러 이벤트 발생Raising multiple events

클래스에서 여러 이벤트를 발생시키는 경우, 컴파일러가 각 이벤트 대리자 인스턴스에 대해 하나의 필드를 생성합니다.If your class raises multiple events, the compiler generates one field per event delegate instance. 이벤트 수가 큰 경우 대리자당 하나의 필드의 스토리지 공간은 허용되지 않습니다.If the number of events is large, the storage cost of one field per delegate may not be acceptable. 이러한 경우를 위해 .NET에서는 이벤트 대리자를 저장하도록 선택한 다른 데이터 구조와 함께 사용할 수 있는 이벤트 속성을 제공합니다.For those situations, .NET provides event properties that you can use with another data structure of your choice to store event delegates.

이벤트 속성은 이벤트 접근자와 함께 이벤트 선언으로 구성됩니다.Event properties consist of event declarations accompanied by event accessors. 이벤트 접근자는 사용자가 정의하는 메서드로서, 스토리지 데이터 구조에서 이벤트 대리자 인스턴스를 추가하거나 제거할 수 있게 합니다.Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. 각 이벤트 대리자는 호출되기 전에 검색되어야 하기 때문에 이벤트 속성은 이벤트 필드보다 속도가 느립니다.Note that event properties are slower than event fields, because each event delegate must be retrieved before it can be invoked. 메모리와 속도 간의 균형을 조정합니다.The trade-off is between memory and speed. 클래스가 자주 발생하는 많은 이벤트를 정의하는 경우 이벤트 속성을 구현합니다.If your class defines many events that are infrequently raised, you will want to implement event properties. 자세한 내용은 방법: 이벤트 속성을 사용하여 여러 이벤트 처리를 참조하세요.For more information, see How to: Handle Multiple Events Using Event Properties.

제목Title 설명Description
방법: 이벤트 발생 및 사용How to: Raise and Consume Events 이벤트의 발생 및 사용에 대한 예제를 포함합니다.Contains examples of raising and consuming events.
방법: 이벤트 속성을 사용하여 여러 이벤트 처리How to: Handle Multiple Events Using Event Properties 이벤트 속성을 사용하여 여러 이벤트를 처리하는 방법을 보여 줍니다.Shows how to use event properties to handle multiple events.
관찰자 디자인 패턴Observer Design Pattern 구독자가 공급자를 등록하고 공급자로부터 알림을 수신하는 데 사용할 수 있는 디자인 패턴에 대해 설명합니다.Describes the design pattern that enables a subscriber to register with, and receive notifications from, a provider.
방법: Web Forms 애플리케이션에서 이벤트 사용How to: Consume Events in a Web Forms Application Web Forms 컨트롤에서 발생한 이벤트를 처리하는 방법을 보여 줍니다.Shows how to handle an event that is raised by a Web Forms control.

참고 항목See also