Event Queue
Event
- 한 object에 의해 어떤 action이 발생했음을 알리는 notification
- .NET에서는 observer design pattern을 사용
event 선언 및 event 발동
// delegate
public delegate void Notify();
public class ProcessBusinessLogic
{
// event
public event Notify ProcessCompleted;
public void StartProcess()
{
Console.WriteLine("Process Started!");
OnProcessCompleted();
}
//protected virtual method
protected virtual void OnProcessCompleted()
{
//등록된 이벤트가 있으면 invoke
ProcessCompleted?.Invoke();
}
}
class Program
{
public static void Main()
{
ProcessBusinessLogic bl = new ProcessBusinessLogic();
// 이벤트를 등록
bl.ProcessCompleted += bl_ProcessCompleted;
bl.StartProcess();
}
// event handler
public static void bl_ProcessCompleted()
{
Console.WriteLine("Process Completed!");
}
}
bulit-in event handler
// 커스텀 인자를 전달
// EventArgs에서 상속
class ProcessEventArgs : EventArgs
{
public bool IsSuccessful { get; set; }
public DateTime CompletionTime { get; set; }
}
public class ProcessBusinessLogic
{
// built-in EventHandler 선언
// 아무 인자도 전달하지 않음
public event EventHandler ProcessCompleted1;
// bool 인자를 전달함
public event EventHandler<bool> ProcessCompleted2;
// 카스텀 이벤트 인자를 전달함
public event EventHandler<ProcessEventArgs> ProcessCompleted3;
var data = new ProcessEventArgs();
public void StartProcess()
{
Console.WriteLine("Process Started!");
// EventArgs.Empty = 이벤트에 전달할 인자가 없음
OnProcessCompleted(EventArgs.Empty);
// bool 인자를 전달
OnProcessCompleted(true);
// 커스텀 인자를 전달
data.IsSuccessful = true;
data.CompletionTime = DateTime.Now;
OnProcessCompleted(data);
}
protected virtual void OnProcessCompleted(EventArgs e)
{
ProcessCompleted1?.Invoke(this, e);
}
protected virtual void OnProcessCompleted(bool IsSuccessful)
{
ProcessCompleted2?.Invoke(this, IsSuccessful);
}
protected virtual void OnProcessCompleted(ProcessEventArgs e)
{
ProcessCompleted3?.Invoke(this, e);
}
}
class Program
{
public static void Main()
{
ProcessBusinessLogic bl = new ProcessBusinessLogic();
// 이벤트를 등록
bl.ProcessCompleted1 += bl_ProcessCompleted1;
bl.ProcessCompleted2 += bl_ProcessCompleted2;
bl.ProcessCompleted3 += bl_ProcessCompleted3;
bl.StartProcess();
}
// event handler
public static void bl_ProcessCompleted1(object sender, EventArgs e)
{
Console.WriteLine("Process Completed!");
}
// event handler
public static void bl_ProcessCompleted2(object sender, bool IsSuccessful)
{
Console.WriteLine("Process " + (IsSuccessful? "Completed Successfully": "failed"));
}
public static void bl_ProcessCompleted3(object sender, ProcessEventArgs e)
{
Console.WriteLine("Process " + (e.IsSuccessful? "Completed Successfully": "failed"));
Console.WriteLine("Completion Time: " + e.CompletionTime.ToLongDateString());
}
}
input 실행 방법
// delegate 선언
public delegate void EventHandler(bool inValue);
// event 선언
public event EventHandler OnEvent;
// delegate에 전달할 함수 정의
private void EventHandler(bool inValue)
{...}
// event에 delegate 추가
OnEvent += EventHandler;
void Update()
{
if ((Input.GetKeyDwon(KeyCode.SPACE)))
{
// 직접 호출
...
// 이벤트로 호출
OnEvent?.Invoke(true);
}
}
- delegate를 사용하든 직접 호출하든 퍼포먼스적인 차이는 없다
- 다만 event를 통해 기능을 분할하면 모듈화를 통한 코드 및 프로젝트 관리가 용이하다는 장점이 있다
delegate를 두고 event를 사용하는 이유?
- code가 delegate를 정의하는 A와 클래스 객체를 통해 delegate를 사용하는 B로 나눠져 있다고 가정한다
// code A
public delegate void YourLoggingHere(); // delegate 정의
public class WhyUseEvents // 클래스 정의
{
// 사용할 delegate 선언
// deletage 등록을 위해 public
public YourLoggingHere MyLogging;
public void MyMainProgram()
{
ExecuteValidation();
}
// delegate 호출 가능
private void ExecuteValidation()
{
// invoke 전에 실행해야 할 코드들...
// ...
if (MyLogging != null)
{
MyLogging.Invoke();
}
}
}
// code B
WhyUseEvents why = new WhyUseEvents(); // 클래스 객체화
// 객체의 delegate에 메서드 등록
why.MyLogging += () =>
{
Console.WriteLine("Hi I am subscribing to the delegate.");
};
// code B에서 delegate를 바로 invoke시킬 수 있음
// invoke 전에 실행해야 할 코드를 무시하는 문제 발생
why.MyLogging.Invoke();
// 해결책
// code A에 event 키워드를 추가한다
public event YourLoggingHere MyLogging;
// 이제 아래와 같은 직접 호출은 불가능하고, 이벤트에 등록하거나 제거만 할 수 있다는 에러가 발생한다
//The event 'WhyUseEvents.MyLogging' can only appear on the left hand side of += or -= (except when used from within the type 'WhyUseEvents')
why.MyLogging.Invoke();
// 이벤트에 등록된 메서드를 clear 하는 방법
why.MyLogging = null;
- delegate를 불가피하게 public으로 선언해야하고, 이를 사용자가 정해진 프로세스를 벗어나 직접 Incoke 가능한 케이스를 방지하기 위해 event 키워드를 사용