이벤트 리스너는 어떻게 작동합니까?


125

오늘 Unity에 대한 강의 중 하나에서 사용자가 버튼을 눌렀는지 확인하면 모든 프레임을 확인하여 플레이어 위치를 업데이트하는 것에 대해 논의했습니다. 누군가는 이것이 비효율적이라고 말하면서 대신 이벤트 리스너를 사용해야합니다.

내 질문은 프로그래밍 언어 또는 적용되는 상황에 관계없이 이벤트 리스너가 어떻게 작동합니까?

내 직감은 이벤트 리스너가 이벤트가 발생했는지 지속적으로 확인한다고 가정합니다. 즉, 시나리오에서는 이벤트가 발생했는지 모든 프레임을 확인하는 것과 다르지 않습니다.

수업 토론을 바탕으로 이벤트 리스너가 다른 방식으로 작동하는 것 같습니다.

이벤트 리스너는 어떻게 작동합니까?


34
이벤트 리스너는 전혀 확인하지 않습니다. "듣기"이벤트가 발생하면 호출됩니다.
Robert Harvey

13
예,하지만 어떻게 "들어"듣습니까? 지속적으로 확인하지 않습니까?
Gary Holiday

28
아니. "이벤트 리스너"는 아마도 단어를 잘못 선택했을 것입니다. 실제로는 "듣지"않습니다. 모든 이벤트 리스너는 다른 메소드와 마찬가지로 이벤트가 실행될 때 호출되기를 기다립니다. 이 방식으로 호출 될 때까지는 아무 것도 수행하지 않습니다.
Robert Harvey

28
버튼을 눌렀는지 확인할 때마다 클럭 사이클 비용이 발생합니다. 이벤트 핸들러 (리스너)는 실제로 버튼을 눌렀을 때만 비용이 발생합니다.
Robert Harvey

45
@RobertHarvey- "리스너"가 여전히 낮은 레벨에서 지속적인 폴링을 필요로하기 때문에 반드시 그런 것은 아닙니다. 자신의 코드 계층에서 하드웨어 인터럽트 등으로 복잡성을 더하기 만하면됩니다. 그리고 그렇습니다. 이것은 일반적으로 더 효율적이지만, 청취가 폴링보다 우수하지 않기 때문에 낮은 수준의 폴링이 C #의 폴링과 하드웨어와 사용자 간의 15 개 계층 추상화보다 더 효율적이기 때문입니다.
Davor Ždralo

답변:


140

사용자가 제공 한 폴링 예제 (버튼마다 프레임이 확인되는 경우)와 달리 이벤트 리스너는 버튼이 눌 렸는지 확인하지 않습니다. 대신 버튼을 누를 때 호출됩니다.

아마도 "이벤트 리스너"라는 용어가 당신을 던지고있을 것입니다. 이 용어는 "리스너 (listener)"가 실제로 무언가를하지 않을 때들을 수있는 무언가를 적극적으로하고 있음을 시사합니다. "리스너 (listener)"는 이벤트에 등록 된 함수 또는 메소드 일뿐입니다. 이벤트가 발생하면 리스너 메소드 ( "이벤트 핸들러")가 호출됩니다.

이벤트 패턴의 장점은 실제로 버튼을 누를 때까지 비용이 들지 않는다는 것입니다. 이벤트는 이벤트를 발생시키기 위해 실행중인 코드를 잠깐 선점하는 "하드웨어 인터럽트"에서 발생하기 때문에 모니터링하지 않고도 이러한 방식으로 처리 할 수 ​​있습니다.

일부 UI 및 게임 프레임 워크는 "메시지 루프"라는 것을 사용합니다. "메시지 루프"는 나중에 (보통 짧은 기간) 실행을 위해 이벤트를 큐에 대기시킵니다. 그러나 해당 이벤트를 먼저 메시지 루프로 가져 오려면 하드웨어 인터럽트가 필요합니다.


54
버튼을 누를 때까지 비용이 들지 않는 이유는 버튼이 "특별"하고 컴퓨터에 인터럽트 및 OS가 사용할 수있는 기타 특수 기능이 있으며 사용자 공간 응용 프로그램으로 추상화되기 때문입니다.
whatsisname

46
@whatsisname 그 사건 동안 매우 깊은 게임 엔진이 인터럽트 작동하지 않는 것 같다,하지만 여전히 사실 루프에서 이벤트 소스 폴링 실제로 후드 아래는. 그것은 더 이벤트 리스너를 추가하는 추가하지 않도록이 폴링, 중앙 및 최적화 단지의 추가 폴링과 복잡성을.
gntskn

7
@PieterGeerkens gntskn은 게임 엔진 루프의 일부로 미해결 이벤트를 확인하는 단계가 있음을 의미한다고 생각합니다. 각 루프 동안 이벤트는 다른 모든 루프 당 한 번의 활동과 함께 처리됩니다. 이벤트 확인을위한 별도의 루프 는 없습니다 .
Joshua Taylor

2
@ Voo :이 게시물 에서이 수준의 세부 사항에 들어 가지 않는 더 많은 이유.
Robert Harvey

2
@Voo : 키보드의 물리적 키와 마우스 버튼과 같은 버튼에 대해 이야기하고 있습니다.
whatsisname

52

웹 페이지 (정보 전송을 시작하는 사람)를 끊임없이 새로 고치지 않고 전자 메일 뉴스 레터 구독 (자신이 보낸 사람이 전송을 시작한 업데이트를 받도록 등록하는 이벤트)과 유사한 이벤트 리스너입니다.

이벤트 시스템은 등록자 목록을 관리하는 이벤트 오브젝트를 사용하여 구현됩니다. 관심있는 객체 ( 구독자 , 리스너 , 델리게이트 등)는 이벤트에 자신을 구독하는 메소드를 호출하여 이벤트에 대한 알림을 받도록 자신을 구독 할 수 있으며, 이로 인해 이벤트가 목록에 추가됩니다. 이벤트가 될 때마다 해고 (용어도 포함 할 수 있습니다 : 전화 , 트리거 , 호출 , 실행 등)들이 이해할 필요가 문맥 어떤 정보를 함께 전달하는 이벤트를 알리고, 그것은 가입자의 각각에 적절한 방법을 호출 어떻게 된 거예요.


38

짧고 불만족스러운 대답은 응용 프로그램이 신호 (이벤트)를 수신하고 루틴이 해당 시점에서만 호출된다는 것입니다.

더 긴 설명은 조금 더 복잡합니다.

클라이언트 이벤트는 어디서 시작됩니까?

각 최신 응용 프로그램 에는 일반적으로 반 숨겨진 내부 "이벤트 루프"가 있으며이를 수신해야하는 올바른 구성 요소로 이벤트를 전달합니다. 예를 들어, "click"이벤트는 현재 마우스 좌표에서 표면이 보이는 버튼으로 전송됩니다. 이것은 가장 간단한 수준입니다. 실제로 OS는 일부 이벤트 및 일부 구성 요소가 메시지를 직접 수신하기 때문에 이러한 디스패치를 ​​많이 수행합니다.

응용 프로그램 이벤트는 어디에서 발생합니까?

운영 체제는 이벤트가 발생할 때 이벤트를 전달합니다. 그들은 그들 자신의 운전자에 의해 통지를 받아 반응 적으로 그렇게합니다.

드라이버는 어떻게 이벤트를 생성합니까?

저는 전문가는 아니지만 일부 사람들은 CPU 인터럽트를 사용합니다. 새로운 데이터를 사용할 수있을 때 제어하는 ​​하드웨어가 CPU에서 핀을 발생시킵니다. CPU는 들어오는 데이터를 처리하는 드라이버를 시작하여 결국 (큐의) 이벤트를 전달한 다음 제어를 OS로 되돌립니다.

보시다시피, 응용 프로그램이 실제로 항상 실행되지는 않습니다. 이벤트가 발생할 때 OS (Sorta)에 의해 시작되는 절차는 많지만 나머지 시간에는 아무것도하지 않습니다.


눈에 띄는 예외가 있습니다. 예를 들어 게임이 다르게 작동하는 게임


10
이 답변은 브라우저에서 마우스 클릭 이벤트와 관련된 폴링이없는 이유를 설명합니다. 하드웨어 생성 인터럽트 => 드라이버가 OS 이벤트로 해석 => 브라우저가 DOM 이벤트로 해석 => JS 엔진이 해당 이벤트에 대한 리스너를 실행합니다.
Tibos

@Tibos는 키보드 이벤트, 타이머 이벤트, 페인트 이벤트 등에 적용됩니다.
Sklivvz

19

술어

  • event : 일어날 수있는 일.

  • 이벤트 발생 : 특정 이벤트 발생; 이벤트가 발생합니다.

  • 이벤트 리스너 : 이벤트 발생을 찾는 것.

  • event handler : 이벤트 리스너가 이벤트 발생을 감지 할 때 발생하는 것입니다.

  • event subscriber : 이벤트 핸들러가 호출해야하는 응답.

이러한 정의는 구현에 의존하지 않으므로 다른 방식으로 구현할 수 있습니다.

이러한 용어 중 일부는 일반적으로 사용자가 서로 구별 할 필요가 없기 때문에 동의어로 오인됩니다.

일반적인 시나리오

  1. 프로그래밍 논리 이벤트.

    • 이벤트는 몇 가지 방법이 호출 될 때입니다.

    • 이벤트 발사는 그 방법에 대한 특정 호출입니다.

    • 이벤트 리스너는 이벤트 핸들러를 호출 각 이벤트 발사에라고 이벤트 방법에 훅입니다.

    • 이벤트 핸들러는 이벤트 가입자의 컬렉션을 호출합니다.

    • 이벤트 가입자이벤트 발생에 대한 응답으로 시스템이 의미하는 모든 행동을 수행합니다.

  2. 외부 행사.

    • 사건 은 관측 가능한 것으로 추론 할 수있는 외부 사건입니다.

    • 이벤트 소성 그 외부 일어나는 발생한 것으로 인식 할 수있는 경우이다.

    • 이벤트 리스너는 어떻게 든 자주 폴링에 의해, 이벤트 발사를 감지 관찰 (들), 다음이 발사 이벤트를 감지하면 이벤트 핸들러를 호출합니다.

    • 이벤트 핸들러는 이벤트 가입자의 컬렉션을 호출합니다.

    • 이벤트 가입자이벤트 발생에 대한 응답으로 시스템이 의미하는 모든 행동을 수행합니다.

폴링 vs. 이벤트의 발사 메커니즘에 후크 삽입

다른 사람들의 요점은 종종 폴링이 필요하지 않다는 것입니다. 이벤트 발생시 이벤트 핸들러가 자동으로 이벤트 핸들러를 호출하도록하여 이벤트 리스너를 구현할 수 있기 때문입니다. 이는 이벤트가 시스템 레벨 발생 일 때이를 구현하는 가장 효율적인 방법입니다.

우체국 직원이 문을 두드리고 직접 우편물을 건네주는 경우 매일 우편함에서 우편물을 확인하지 않아도됩니다.

그러나 이벤트 리스너는 폴링을 통해 작동 할 수도 있습니다. 폴링이 반드시 특정 값이나 다른 관찰 가능한 값을 확인할 필요는 없습니다. 더 복잡 할 수 있습니다. 그러나 전반적으로 폴링의 요점은 일부 이벤트가 발생했을 때 응답 할 수 있도록 추론하는 것입니다.

유추하여 우편 배달원이 우편물을 보내기 만하면 우편함을 매일 확인해야합니다. 우체국 직원에게 문을 두드리라 고 지시 할 수 있다면이 폴링 작업을 수행 할 필요는 없지만 종종 가능하지는 않습니다.

연쇄 이벤트 로직

많은 프로그래밍 언어에서 키보드의 키를 누르거나 특정 시간에 방금 호출되는 이벤트를 작성할 수 있습니다. 외부 이벤트이지만 폴링 할 필요는 없습니다. 왜?

운영 체제가 사용자를 폴링하기 때문입니다. 예를 들어, Windows는 키보드 상태 변경과 같은 것을 확인하고이를 감지하면 이벤트 가입자를 호출합니다. 따라서 키보드 프레스 이벤트에 가입하면 실제로는 폴링 이벤트에 대한 가입자 자체 인 이벤트에 가입하게됩니다.

유사하게, 당신이 아파트 단지에 살고 있고 우체국 직원이 공동 우편 영수증 지역으로 우편물을 가져옵니다. 그런 다음 운영 체제와 유사한 작업자가 모든 사람을 위해 해당 메일을 확인하여 무언가를받은 사람들의 아파트로 메일을 배달 할 수 있습니다. 이렇게하면 다른 모든 사람이 메일 수신 영역을 폴링해야하는 번거 로움을 덜 수 있습니다.


내 직감은 이벤트 리스너가 이벤트가 발생했는지 지속적으로 확인한다고 가정합니다. 즉, 시나리오에서는 이벤트가 발생했는지 모든 프레임을 확인하는 것과 다르지 않습니다.

수업 토론을 바탕으로 이벤트 리스너가 다른 방식으로 작동하는 것 같습니다.

이벤트 리스너는 어떻게 작동합니까?

의심 한대로 이벤트 폴링을 통해 작동 할 수 있습니다 . 그리고 이벤트가 키보드 키를 누르는 것과 같이 외부에서 발생하는 문제와 관련이있는 경우 어느 시점에서 폴링이 발생해야합니다.

이벤트에 반드시 폴링이 필요하지는 않습니다. 예를 들어, 이벤트가 단추를 눌렀을 때 발생하는 경우 해당 단추의 이벤트 리스너는 마우스 클릭이 단추를 누르는 것으로 판단 될 때 GUI 프레임 워크가 호출 할 수있는 메소드입니다. 이 경우 마우스 클릭이 감지 되려면 여전히 폴링이 발생해야하지만 마우스 리스너는 이벤트 체인을 통해 기본 폴링 메커니즘에 연결된보다 수동적 인 요소입니다.

업데이트 : 저수준 하드웨어 폴링

USB 장치 및 기타 최신 통신 프로토콜에는 상호 작용을위한 다소 매혹적인 네트워킹과 유사한 프로토콜 세트가있어 키보드 및 마우스를 포함한 I / O 장치가 임시 토폴로지 에 참여할 수 있습니다.

흥미롭게도 " 인터럽트 "는 매우 필수적인 동기식이므로 임시 네트워킹 토폴로지를 처리하지 않습니다 . 이 문제를 해결하기 위해 " 인터럽트 "는 " 인터럽트 트랜잭션 " (USB 컨텍스트) 또는 " 메시지 신호 인터럽트 " (PCI 컨텍스트 ) 라고하는 비동기 우선 순위가 높은 패킷으로 일반화되었습니다 . 이 프로토콜은 USB 사양에 설명되어 있습니다.

여기에 이미지 설명을 입력하십시오

- " 그림 8-31. "범용 직렬 버스 사양, 개정 2.0 "의 벌크 / 제어 / 인터럽트 OUT 트랜잭션 호스트 상태 머신 " -222 페이지; PDF-250 페이지 (2000-04-27)

요점은 I / O 장치 및 통신 구성 요소 (USB 허브 등)가 기본적으로 네트워크 장치처럼 작동하는 것 같습니다. 따라서 포트를 폴링해야하는 메시지를 보냅니다. 이를 통해 전용 하드웨어 라인이 필요하지 않습니다.

윈도우와 같은 운영 체제가 폴링 과정 자체를 처리하는 것, 예에 설명 된대로 에 대한 MSDN 문서 USB_ENDPOINT_DESCRIPTOR 제어하는 방법에 대해 설명합니다 얼마나 자주 윈도우 여론 조사 인터럽트 / 등시성 메시지에 대한 USB 호스트 컨트롤러 :

bInterval값에는 인터럽트 및 등시성 엔드 포인트에 대한 폴링 간격이 포함됩니다. 다른 유형의 엔드 포인트의 경우이 값을 무시해야합니다. 이 값은 장치의 펌웨어 구성을 반영합니다. 드라이버는 변경할 수 없습니다.

폴링 간격은 장치 속도 및 호스트 컨트롤러 유형과 함께 드라이버가 인터럽트 또는 등시 전송을 시작해야하는 빈도를 결정합니다. 의 값은 bInterval고정 된 시간 을 나타내지 않습니다. 상대 값이며 실제 폴링 주파수는 장치와 USB 호스트 컨트롤러가 저속, 전속 또는 고속으로 작동하는지에 따라 달라집니다.

- "USB_ENDPOINT_DESCRIPTOR 구조" , Microsoft 하드웨어 개발 센터

DisplayPort 와 같은 최신 모니터 연결 프로토콜도 동일한 것으로 보입니다.

멀티 스트림 전송 (MST)

  • DisplayPort 버전 1.2에 추가 된 MST (Multi-Stream Transport)

    • Ver.1.1a에서는 SST (Single-Stream Transport) 만 사용할 수있었습니다.
  • MST는 단일 커넥터를 통해 여러 A / V 스트림을 전송합니다

    • 최대 63 개 스트림; "레인 당 스트림"이 아님

      • 전송 된 스트림들 사이에는 동기 성이 없다. 하나의 스트림은 블랭킹 기간에 있고 다른 스트림은 그렇지 않습니다.
    • 연결 지향 운송

      • 스트림 전송을 시작하기 전에 AUX CH를 통한 메시지 트랜잭션을 통해 설정된 스트림 소스에서 대상 스트림 싱크로의 경로

      • 나머지 스트림에 영향을주지 않고 스트림 추가 / 삭제

여기에 이미지 설명을 입력하십시오

- 슬라이드 # 14를 "DisplayPortTM ver.1.2 도서 개요" (2010-12-06)

이 추상화는 한 연결에서 3 개의 모니터를 실행하는 것과 같은 몇 가지 깔끔한 기능을 허용합니다.

또한 DisplayPort Multi-Stream Transport를 사용하면 3 개 이상의 장치를 함께 연결할 수 있지만 반대의 "소비자"지향 구성으로 단일 출력 포트에서 여러 디스플레이를 동시에 구동 할 수 있습니다.

- "DisplayPort" , Wikipedia

개념적으로,이 점에서 벗어나는 요점은 폴링 메커니즘이보다 일반화 된 직렬 통신을 허용한다는 것입니다. 이는보다 일반적인 기능을 원할 때 매우 좋습니다. 따라서 하드웨어와 OS는 논리 시스템에 대해 많은 폴링을 수행합니다. 그러면 이벤트를 구독하는 소비자는 자체 폴링 / 메시지 전달 프로토콜을 작성할 필요없이 하위 수준 시스템에서 처리하는 세부 정보를 즐길 수 있습니다.

궁극적으로 키 누름과 같은 이벤트는 소프트웨어 수준의 필수 이벤트 발생 메커니즘에 도달하기 전에 다소 흥미로운 일련의 이벤트를 거치는 것으로 보입니다.


마지막 단락과 관련하여 일반적으로 낮은 수준에서 폴링이 수행되지 않으며 운영 체제는 주변 장치에 의해 트리거되는 하드웨어 인터럽트에 반응합니다. 컴퓨터에는 일반적으로 많은 연결된 장치 (마우스, 키보드, 디스크 드라이브, 네트워크 카드)가 있으며 이러한 장치를 모두 폴링하는 것은 매우 비효율적입니다.
Barmar

그러나 메일 배달에 대한 귀하의 비유는 더 높은 수준의 활동을 설명하는 방법입니다.
Barmar

1
@Barmar Ya는 장치를 USB 연결로 옮길 때 직접 PS / 2 키보드처럼 인터럽트를 생성하는 것에서 USB 키보드처럼 폴링을 요구하는 방법에 대해 많은 이야기가 있었고 일부 소스 는 폴링은 CPU에 의해 수행됩니다. 그러나 다른 소식통 은 폴링을 CPU의 인터럽트로 변환하는 특수 컨트롤러에서 수행되었다고 주장합니다.
Nat

@Barmar 어느 것이 올바른지 알고 싶습니까? CPU가 다른 것보다 폴링을 수행한다고 주장하는 소스가 더 많았지 만 특수 컨트롤러가 더 합리적이라고 생각합니다. Arduino 및 기타 임베디드 장치는 CPU가 폴링을 수행 해야하는 경향이 있다고 생각하지만 x86 유형 장치에 대해서는 몰랐습니다.
Nat

1
누구나이 답변을 업데이트 할 수 있다고 확인하면 USB로 연결된 것과 같은 최신 I / O 장치 가 CPU 제어를 우회하여 메모리에 직접 쓰는 것으로 생각합니다 (이는 빠르고 효율적이며 보안적인 이유입니다) 때때로 위험 ). 그런 다음 새로운 메시지를 확인하기 위해 메모리를 폴링하려면 최신 OS가 필요합니다.
Nat

8

풀 대 푸시

이벤트가 발생했는지 또는 특정 상태에 도달했는지 확인하는 두 가지 주요 전략이 있습니다. 예를 들어 중요한 배달을 기다리는 것을 상상해보십시오.

  • 당기기 : 10 분마다 사서함으로 내려가 배달되었는지 확인합니다.
  • 푸시 : 배달원에게 배달 할 때 전화를 걸도록 지시합니다.

(또한 폴링이라고도 함) 접근 방식은 간단하다 : 당신이 어떤 특별한 기능없이 구현할 수 있습니다. 반면에, 표시 할 항목이없는 추가 검사를 수행 할 위험이 있기 때문에 종종 효율성이 떨어집니다.

반면에, 푸쉬 접근법은 일반적으로 더 효율적입니다. 코드는 할 일이있을 때만 실행됩니다. 반면에 리스너 / 관찰자 / 콜백 1 등록을위한 메커니즘이 필요합니다 .

1 우체부 직원은 불행히도 그러한 메커니즘이 부족합니다.


1

구체적으로 화합에 대하여-매 프레임마다 폴링하는 것 외에 플레이어의 입력을 확인하는 다른 방법은 없습니다. 이벤트 리스너를 작성하려면 여전히 폴링을 수행하기 위해 "이벤트 시스템"또는 "이벤트 관리자"와 같은 오브젝트가 필요하므로 문제점을 다른 클래스로만 푸시합니다.

이벤트 관리자가 있으면 한 프레임마다 입력을 폴링하는 클래스가 하나 뿐이지 만,이 클래스는 리스너를 반복하고 호출해야하기 때문에 성능에 이점이 없습니다. 디자인 (예 : 청취자가 몇 명이고 플레이어가 입력을 얼마나 자주 사용하는지)과 같이 실제로 비용이 더 많이들 수 있습니다.

이 모든 것 외에도 골든 규칙을 기억하십시오. 조기 최적화는 모든 악의 근원이며 , 특히 비디오 게임에서 특히 그렇습니다. 각 프레임의 렌더링 프로세스가 너무 비싸서 이와 같은 작은 스크립트 최적화는 완전히 중요하지 않습니다.


중앙 이벤트 루프를 최적화로 보지 않고 폴링과 반대로 더 읽기 쉽고 이해하기 쉬운 코드를 작성하는 것이 코드베이스 전체에 퍼져 있습니다. 또한 "합성"이벤트 및 게임 엔진 폴링에서 발생하지 않는 이벤트도 허용합니다.
BlackJack

@BlackJack 나는 동의하고 나는 보통 이런 식으로 직접 코딩하지만 OP는 성능에 대해 물었다. Btw에서 Unity는 놀랍게도 거의 모든 곳에서 정적 기능을 갖는 것과 같이 의심스러운 코드 디자인 결정을 많이 내 렸습니다.
Dunno

1

버튼 누름 또는 타이머 오버플로 또는 메시지 도착과 같은 이벤트를 처리하는 OS / 프레임 워크를 지원하지 않는 한 폴링을 사용하여이 이벤트 리스너 패턴을 구현해야합니다 (어딘가 아래).

그러나 바로 성능상의 이점이 없기 때문에이 디자인 패턴에서 벗어나지 마십시오. 이벤트 처리에 대한 기본 지원 여부에 관계없이 사용해야하는 이유는 다음과 같습니다.

  1. 코드가 깨끗하고 격리 된 것처럼 보입니다 (물론 올바르게 구현 된 경우)
  2. 이벤트 핸들러를 기반으로하는 코드는 변경 사항을 더 잘 유지합니다 (일반적으로 일부 이벤트 핸들러 만 수정하므로)
  3. 기본 이벤트 지원을 통해 플랫폼으로 이동하는 경우 기존 이벤트 핸들러를 재사용하고 폴링 코드를 제거 할 수 있습니다.

결론-토론에 참여하여 운이 좋았으며 설문 조사에 대한 대안을 배웠습니다. 이 개념을 실제로 적용 할 수있는 기회를 찾으면 코드가 얼마나 우아 할 수 있는지 감사하게 생각할 것입니다.


1

대부분의 이벤트 루프 는 운영 체제에서 제공하는 일부 폴링 멀티플렉싱 프리미티브 위에 구축됩니다. Linux에서이 기본 요소는 종종 poll(2) 시스템 호출 (이전 시스템 호출 일 수 있음 select)입니다. GUI 애플리케이션에서 디스플레이 서버 (예 : Xorg 또는 Wayland )는 애플리케이션 ( 소켓 (7) 또는 파이프 (7)을 통해 )과 통신 중입니다. X Window 시스템 프로토콜 및 아키텍처에 대해서도 읽어보십시오 .

이러한 폴링 프리미티브는 효율적입니다. 커널은 실제로 일부 입력이 완료되고 일부 인터럽트가 처리되면 프로세스를 깨 웁니다.

구체적으로, 위젯 툴킷 라이브러리는 디스플레이 서버와 통신하여 메시지를 대기하고 이러한 메시지를 위젯으로 디스패치합니다. Qt 또는 GTK 와 같은 툴킷 라이브러리 는 매우 복잡합니다 (수백만 줄의 소스 코드). 키보드와 마우스는 디스플레이 서버 프로세스에서만 처리됩니다 (이러한 입력은 클라이언트 응용 프로그램으로 전송되는 이벤트 메시지로 변환됩니다).

(저는 단순화하고 있습니다. 실제로는 훨씬 더 복잡합니다)


1

순수 폴링 기반 시스템에서 특정 조치가 언제 발생하는지 알고 자하는 서브 시스템은 해당 조치가 발생할 때마다 일부 코드를 실행해야합니다. 불필요하게 고유하지 않은 이벤트가 발생한 후 10ms 이내에 각각 반응해야하는 많은 서브 시스템이있는 경우, 모두 해당 이벤트가 발생했는지 최소 100 회 / 초를 확인해야합니다. 이러한 서브 시스템이 다른 스레드 (또는 더 나쁜 프로세스) 프로세스에있는 경우 모든 스레드 또는 프로세스를 100x / 초로 전환해야합니다.

응용 프로그램이 감시 할 많은 것들이 다소 유사하다면 중앙 집중식 모니터링 하위 시스템 (아마도 테이블 기반)을 사용하는 것이 더 효과적 일 수 있습니다. 예를 들어, 32 개의 스위치가있는 경우 플랫폼에 모든 32 개의 스위치를 한 번에 한 단어로 읽는 기능이있어 모니터 코드가 폴링간에 스위치가 변경되었는지 여부를 확인할 수 있습니다. 어떤 코드에 관심이 있는지 걱정하십시오.

변경 될 때 통지를 원하는 서브 시스템이 많이있는 경우, 전용 모니터링 서브 시스템을 사용하면 관심이있는 이벤트가 발생할 때 다른 서브 시스템에 통지하는 것이 각 서브 시스템이 자체 이벤트를 폴링하는 것보다 더 효율적일 수 있습니다. 그러나 아무도 이벤트에 관심이없는 경우 전용 모니터링 하위 시스템을 설정하면 순수한 리소스 낭비가됩니다. 이벤트에 관심이있는 서브 시스템이 몇 개만있는 경우, 관심있는 이벤트를 감시하는 데 드는 비용은 범용 전용 모니터링 서브 시스템을 설정하는 비용보다 적을 수 있지만 손익분기 점 포인트는 플랫폼마다 크게 다릅니다.


0

이벤트 리스너는 메시지를 기다리는 귀와 같습니다. 이벤트가 발생하면 이벤트 리스너로 선택된 서브 루틴이 이벤트 인수를 사용하여 작동합니다.

항상 중요한 두 가지 데이터가 있습니다 : 이벤트가 발생하는 순간과이 이벤트가 발생하는 객체. 다른 주장은 일어난 일에 대한 더 많은 데이터입니다.

이벤트 리스너는 발생하는 반응을 지정합니다.


0

이벤트 리스너는 발행자 / 구독 패턴을 따릅니다 ( 구독자 로서)

가장 간단한 형식으로 게시 개체는 게시해야 할 때 수행 할 구독자 지침 목록을 유지 관리합니다.

여기 subscribe(x)에는 x가 이벤트 핸들러가 이벤트를 처리하도록 설계된 방식에 따라 달라지는 일종의 메소드가 있습니다. subscribe (x)가 호출되면 x는 구독자 지침 / 참조의 게시자 목록에 추가됩니다.

게시자는 이벤트를 처리하기위한 모든 논리를 포함하거나 전혀 포함하지 않을 수 있습니다. 이벤트 발생시 가입자에게 지정된 로직으로 통지 / 변환하기 위해 가입자에 대한 참조가 필요할 수 있습니다. 로직을 포함하지 않을 수 있으며 이벤트를 처리 할 수있는 구독자 객체 (메소드 / 이벤트 리스너)가 필요합니다. 둘 다 혼합되어있을 가능성이 높습니다.

이벤트가 발생하면 게시자는 가입자의 지침 / 참조 목록에있는 각 항목에 대해 해당 논리를 반복하여 실행합니다.

이벤트 핸들러가 아무리 복잡해 보이더라도 핵심적으로이 간단한 패턴을 따릅니다.

이벤트 리스너 예제의 경우, 메소드 / 함수 / 명령 / 이벤트 리스너를 이벤트 핸들러의 subscribe () 메소드에 제공하십시오. 이벤트 핸들러는 메소드를 구독자 콜백 목록에 추가합니다. 이벤트가 발생하면 이벤트 핸들러는 목록을 반복하고 각 콜백을 실행합니다.

실제 예를 들어 Stack Exchange의 뉴스 레터를 구독하면 프로필에 대한 참조가 구독자의 데이터베이스 테이블에 추가됩니다. 뉴스 레터를 게시 할 때 참조는 뉴스 레터 템플릿을 채우는 데 사용되며 이메일로 전송됩니다. 이 경우 x는 단순히 귀하를 참조하며, 게시자는 모든 가입자에게 사용되는 일련의 내부 지침이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.