delegate 02. Event
대리자와 이벤트는 같은 개념이다.
하지만 이벤트가 대리자와 다른점은, 이벤트는 메서드 안에서만 호출해서 사용 가능하다는 점이다.
이벤트를 발생시키는 쪽과, 발생된 이벤트가 반영되는 객체만 구분하면 된다.
eg) 버튼 클릭 > 이벤트(대리자) > 레이블 수정
01. 이벤트 선언 방법
이벤트는 대리자를 event 한정자로 수식해서 만든다.
[이벤트_키워드] [대리자_이름] [이벤트_이름];
delegate int A(String str);
class Temp
{
public event A EventHandler;
public void Func(string msg)
{
EventHandler(msg);
}
}
02. 이벤트 이해
이벤트를 발생시키는 객체와, 발생된 이벤트가 영향받는 객체만 구분하면
이벤트 기반(Event Driven) 구조는 사실 끝이다.
// C++ Qt의 Connect Signal, slot 개념에 비유한 코드
using System;
namespace EventTest
{
delegate void Callback(string message);
class Button
{
// 이벤트는 C++ Qt의 Signal이다.
// 이벤트를 가지는 코드 쪽은, 이벤트를 시작하는 쪽이다.
public event Callback CollbackEvent;
public void DoSomething(int number)
{
int temp = number % 10;
if (temp != 0 && temp % 3 == 0)
{
CollbackEvent(String.Format("{0} : 짝", number));
}
}
}
class MainApp
{
// 이벤트의 영향을 받아 이벤트의 결과가 반영되는 곳이다.
// 18: CollbackEvent(String.Format("{0} : 짝", number));
// 소스코드에서 동일한 매개변수를 전달받는다.
static public void Label(string message)
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
Button btn = new Button();
// 이벤트(콜백, 대리자)에 연결하는 쪽은, 이벤트의 결과가 반영되는 쪽이다.
btn.CollbackEvent += new Callback(Label);
for (int i = 1; i < 30; i++)
{
btn.DoSomething(i);
}
}
}
}
// 이것이 c#이다. 교재 496쪽 소스코드
using System;
namespace EventTest
{
delegate void EventHandler(string message);
class MyNotifier
{
public event EventHandler SomethingHappened;
public void DoSomething(int number)
{
int temp = number % 10;
if ( temp != 0 && temp % 3 == 0)
{
SomethingHappened(String.Format("{0} : 짝", number));
}
}
}
class MainApp
{
static public void MyHandler(string message)
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
MyNotifier notifier = new MyNotifier();
notifier.SomethingHappened += new EventHandler(MyHandler);
for (int i = 1; i < 30; i++)
{
notifier.DoSomething(i);
}
}
}
}
이벤트 실행 흐름
예제 1
레이블과 버튼이 있다고 가정한다.
버튼을 누를때, 레이블의 텍스트가 바뀌도록 이벤트 처리한다고 가정하여 구현한다.
using System;
namespace delegate_test4
{
// [1] 이벤트를 만들 대리자 선언
delegate void A(string sender);
// 레이블 객체라고 가정한다.
class Label
{
private string title;
public Label(string name)
{
this.title = name;
}
// 레이블의 텍스트가 바뀐다고 가정한다.
public void run(string run_msg)
{
Console.WriteLine(run_msg + title + "에서 출력!");
}
}
// 버튼은 버튼이고, 레이블은 레이블이다. 서로 다른 객체다.
// 서로 다른 두 객체를 연결해주는 작업은, 버튼이나 레이블 객체에서 하지 않는다.
class Program
{
static void Main(string[] args)
{
// 레이블 4개를 만든다고 가정한다.
Label lbl1 = new Label("레이블1");
Label lbl2 = new Label("레이블2");
Label lbl3 = new Label("레이블3");
Label lbl4 = new Label("레이블4");
// [5] 버튼 객체를 만들고
button btn = new button();
// [6] 버튼의 이벤트 핸들러에, 레이블의 함수 4개를 연결한다.
// 이벤트가 동작하면 실행될 함수를 이벤트에 연결한다,.
// 예로 레이블 문장 업데이트 기능
btn.btn_EventHandler += lbl1.run;
btn.btn_EventHandler += lbl2.run;
btn.btn_EventHandler += lbl3.run;
btn.btn_EventHandler += lbl4.run;
// [7] 버튼의 함수가 동작한다.
btn.RunEvent();
}
}
// [2] 버튼 객체라고 가정한다.
class button
{
// [3] 버튼 안에 이벤트 대리자(핸들러)를 만든다.
public event A btn_EventHandler;
public void RunEvent()
{
//[4] 버튼의 함수가 실행되면, 이벤트 핸들러가 실행된다.
btn_EventHandler($"버튼 객체의 버튼 클릭 이벤트가 발생 >> ");
}
}
}
예제 2
카운팅이라는 로직을 가진 객체의 이벤트가 동작할때마다, 텍스트박스 객체에 출력된다고 가정한다.
using System;
namespace delegate_test4
{
delegate void A (string sender);
class TextBox
{
private string title;
public TextBox(string name)
{
this.title = name;
}
public void run(string run_msg)
{
Console.WriteLine( run_msg + title + "에서 출력!");
}
}
class Program
{
static void Main(string[] args)
{
TextBox TB1 = new TextBox("텍스트창1");
TextBox TB2 = new TextBox("텍스트창2");
TextBox TB3 = new TextBox("텍스트창3");
TextBox TB4 = new TextBox("텍스트창4");
Counting cnt = new Counting();
cnt.Cnt_EventHandler += TB1.run;
cnt.Cnt_EventHandler += TB2.run;
cnt.Cnt_EventHandler += TB3.run;
cnt.Cnt_EventHandler += TB4.run;
cnt.nCnt();
}
}
class Counting
{
public event A Cnt_EventHandler;
public void nCnt()
{
for (int i = 0; i < 10; i++)
{
Cnt_EventHandler($"이벤트, {i+1}회 실행 >> ");
}
}
}
}
예제3
button1 이라는 객체에, button1.Click 이벤트에, Form1의 button1_click( ) 함수가 등록되었다.
"Button 객체의 Event" 라는 대리자가 실행되면, 윈폼의 함수, 윔폼의 컨트롤, 또는 특정 실행 로직을 가진 함수가 실행되도록 구현하는 개념이다.
예제4
윈폼 파일 복사 (동기)
해당 로직은 동기화 방식으로, 파일 복사 실행중에는 UI가 멈춤
event_test 프로젝트 경로에 "파일 복사"에 사용 할 파일 src.mp4 파일이 있어야 합니다.
이벤트 제공자 : button1.click
이벤트 가입자 : FileManager
환경: Visual Studio 2022, net8.0
예제5
윈폼 파일 복사 (비동기)
event_test 프로젝트 경로에 "파일 복사"에 사용 할 파일 src.mp4 파일이 있어야 합니다.
이벤트 제공자 : FileManager
이벤트 가입자 : Form1
환경: Visual Studio 2022, net8.0
댓글
이 글 공유하기
다른 글
-
delegate 01.
delegate 01.
2024.03.04 -
C# 버전과 개발환경
C# 버전과 개발환경
2023.03.17 -
1. 프로그래밍과 C#
1. 프로그래밍과 C#
2023.03.16