본문 바로가기

대리자와 이벤트는 같은 개념이다.

하지만 이벤트가 대리자와 다른점은, 이벤트는 메서드 안에서만 호출해서 사용 가능하다는 점이다.

이벤트를 발생시키는 쪽과, 발생된 이벤트가 반영되는 객체만 구분하면 된다.

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

윈폼 파일 복사 (동기)

(동영상 링크 ~ 8:00)

 

해당 로직은 동기화 방식으로, 파일 복사 실행중에는 UI가 멈춤

 

event_test  프로젝트 경로에  "파일 복사"에 사용 할 파일 src.mp4 파일이 있어야 합니다.

 

이벤트 제공자 : button1.click

이벤트 가입자 : FileManager

 

환경: Visual Studio 2022, net8.0

event_test.zip
16.36MB

 

 

예제5

윈폼 파일 복사 (비동기)

(동영상 링크 8:00 ~ )

 

event_test  프로젝트 경로에  "파일 복사"에 사용 할 파일 src.mp4 파일이 있어야 합니다.

 

이벤트 제공자 : FileManager 

이벤트 가입자 : Form1

 

환경: Visual Studio 2022, net8.0

event_test (2).zip
16.43MB

 

 

BasicLike

어? 나 프로그래밍 좋아하네?