Jak działa detektor zdarzeń?


125

Podczas jednego z moich dzisiejszych wykładów na temat Unity omawialiśmy aktualizację naszej pozycji gracza, sprawdzając każdą klatkę, czy użytkownik ma wciśnięty przycisk. Ktoś powiedział, że to było nieefektywne i zamiast tego powinniśmy użyć detektora zdarzeń.

Moje pytanie brzmi: niezależnie od języka programowania lub sytuacji, w której jest stosowany, jak działa detektor zdarzeń?

Moja intuicja zakłada, że ​​detektor zdarzeń stale sprawdza, czy zdarzenie zostało uruchomione, co oznacza, że ​​w moim scenariuszu nie będzie inaczej niż sprawdzanie każdej klatki, jeśli zdarzenie zostało uruchomione.

Na podstawie dyskusji w klasie wydaje się, że detektor zdarzeń działa w inny sposób.

Jak działa detektor zdarzeń?


34
Detektor zdarzeń w ogóle nie sprawdza. Jest wywoływany, gdy zdarzenie „nasłuchuje” pożarów.
Robert Harvey

13
Tak, ale jak to „słucha”, czy nie będzie ciągle sprawdzać?
Gary Holiday

28
Nie. „Event Listener” to prawdopodobnie zły wybór słów; tak naprawdę wcale nie „słucha”. Wszystko, co robi detektor zdarzeń, czeka, aż zostanie wywołane przez zdarzenie w momencie jego uruchomienia, podobnie jak każda inna metoda. Dopóki nie zostanie wywołany w ten sposób, w ogóle nic nie robi.
Robert Harvey

28
Za każdym razem, gdy sprawdzasz, czy przycisk jest wciśnięty, kosztuje to tyle cykli zegara. Moduł obsługi zdarzeń (detektor) kosztuje tylko wtedy, gdy przycisk zostanie naciśnięty.
Robert Harvey

45
@RobertHarvey - niekoniecznie, ponieważ „słuchacze” wciąż potrzebują ciągłego odpytywania na niższym poziomie. Po prostu przesuwasz złożoność z własnej warstwy kodu głębiej w dół do przerwań sprzętowych lub cokolwiek innego. I tak, zwykle będzie to bardziej wydajne, ale nie dlatego, że słuchanie jest lepsze niż odpytywanie, to dlatego, że odpytywanie na niższym poziomie jest wydajniejsze niż odpytywanie z C # i 15 warstw abstrakcji między tobą a sprzętem.
Davor Ždralo

Odpowiedzi:


140

W przeciwieństwie do podanego przykładu odpytywania (gdzie przycisk jest sprawdzany w każdej ramce), detektor zdarzeń nie sprawdza, czy przycisk jest w ogóle wciśnięty. Zamiast tego jest wywoływany po naciśnięciu przycisku.

Być może rzuca cię termin „detektor zdarzeń”. Termin ten sugeruje, że „słuchacz” aktywnie robi coś, aby słuchać, podczas gdy w rzeczywistości nic nie robi. „Detektor” jest jedynie funkcją lub metodą subskrybującą zdarzenie. Po uruchomieniu zdarzenia wywoływana jest metoda detektora („moduł obsługi zdarzeń”).

Zaletą schematu zdarzeń jest to, że dopóki przycisk nie zostanie wciśnięty, nie ma żadnych kosztów. Zdarzenie można obsłużyć w ten sposób bez monitorowania, ponieważ pochodzi ono z tak zwanego „przerwania sprzętowego”, które przez krótki czas zapobiega uruchomieniu uruchomionego kodu.

Niektóre interfejsy użytkownika i gry wykorzystują coś, co nazywa się „pętlą komunikatów”, która kolejkuje zdarzenia w celu ich wykonania w późniejszym (zwykle krótkim) okresie, ale nadal potrzebujesz przerwania sprzętowego, aby uzyskać to zdarzenie w pętli komunikatów.


54
Warto wspomnieć, że dopóki przycisk nie zostanie naciśnięty, nie ma kosztów, ponieważ przyciski są „specjalne”, komputer ma przerwania i inne specjalne funkcje, z których system operacyjny może korzystać, które są abstrakcyjne w aplikacjach przestrzeni użytkownika.
whatsisname

46
@whatsisname, chociaż jest to bardzo głęboko pod maską, w praktyce silniki gier prawdopodobnie nie działają z przerwaniami, ale w rzeczywistości nadal odpytują źródło zdarzenia w pętli. Po prostu odpytywanie jest scentralizowane i zoptymalizowane, dzięki czemu dodanie większej liczby detektorów zdarzeń nie powoduje dodatkowego odpytywania i złożoności.
gntskn

7
@PieterGeerkens Domyślam się, że gntskn oznaczało, że w ramach pętli silnika gry jest krok, który sprawdza, czy nie ma zaległych zdarzeń. Zdarzenia będą przetwarzane podczas każdej pętli wraz ze wszystkimi innymi działaniami raz na pętlę. Nie byłoby osobnej pętli do sprawdzania zdarzeń.
Joshua Taylor

2
@Voo: Tym bardziej nie warto wchodzić w ten poziom szczegółowości w tym poście.
Robert Harvey

2
@Voo: Mówię o przyciskach, takich jak fizyczne klawisze na klawiaturze i przyciski myszy.
whatsisname

52

Słuchacz wydarzeń podobny do subskrypcji biuletynu e-mailowego (rejestrujesz się, aby otrzymywać aktualizacje, których transmisja jest później inicjowana przez nadawcę), zamiast niekończącego się odświeżania strony internetowej (gdzie to Ty inicjujesz przesyłanie informacji).

System zdarzeń jest implementowany przy użyciu obiektów zdarzeń, które zarządzają listą subskrybentów. Zainteresowane obiekty (zwane subskrybentami , słuchaczami , delegatami itp.) Mogą subskrybować się, aby otrzymywać informacje o zdarzeniu, wywołując metodę, która subskrybuje się do zdarzenia, co powoduje, że zdarzenie dodaje je do swojej listy. Ilekroć zdarzenie jest uruchamiane (terminologia może również obejmować: wywoływane , wywoływane , wywoływane , uruchamiane itp.) , Wywołuje odpowiednią metodę dla każdego z subskrybentów, aby poinformować ich o zdarzeniu, przekazując wszelkie informacje kontekstowe, które muszą zrozumieć co się stało.


38

Krótka, niezadowalająca odpowiedź jest taka, że ​​aplikacja odbiera sygnał (zdarzenie) i że procedura jest wywoływana tylko w tym momencie.

Dłuższe wyjaśnienie jest nieco bardziej zaangażowane.

Skąd pochodzą wydarzenia dla klientów?

Każda nowoczesna aplikacja ma wewnętrzną, zwykle częściowo ukrytą „pętlę zdarzeń”, która rozsyła zdarzenia do odpowiednich komponentów, które powinny je odbierać. Na przykład zdarzenie „kliknięcie” jest wysyłane do przycisku, którego powierzchnia jest widoczna przy bieżących współrzędnych myszy. To jest na najprostszym poziomie. W rzeczywistości system operacyjny wykonuje większość tego wysyłania, ponieważ niektóre zdarzenia i niektóre komponenty będą odbierać wiadomości bezpośrednio.

Skąd pochodzą zdarzenia związane z aplikacją?

Systemy operacyjne wywołują zdarzenia w miarę ich występowania. Robią to reaktywnie, powiadamiani przez własnych kierowców.

Jak kierowcy generują zdarzenia?

Nie jestem ekspertem, ale na pewno niektórzy używają przerwań procesora: kontrolowany przez nich sprzęt podnosi pin procesora, gdy dostępne są nowe dane; CPU odpala sterownik, który obsługuje przychodzące dane, które ostatecznie generują (kolejkę) zdarzeń do wysłania, a następnie zwracają kontrolę z powrotem do systemu operacyjnego.

Jak więc widzisz, twoja aplikacja tak naprawdę nie działa przez cały czas. Jest to szereg procedur, które są uruchamiane przez system operacyjny (w pewnym sensie), gdy zdarzają się zdarzenia, ale przez resztę czasu nic nie robi.


istnieją godne uwagi wyjątki, np. Gry raz, które mogą robić coś inaczej


10
Ta odpowiedź wyjaśnia, dlaczego nie ma odpytywania o zdarzenia kliknięcia myszy w przeglądarce. Sprzęt generuje przerwanie => sterownik rozpoznaje zdarzenie systemu operacyjnego => przeglądarka rozpoznaje zdarzenie DOM => silnik JS uruchamia detektor dla tego zdarzenia.
Tibos

@Tibos afaict dotyczy to również wydarzeń na klawiaturze, wydarzeń z timerem, wydarzeń malarskich itp.
Sklivvz

19

Terminologia

  • zdarzenie : rodzaj rzeczy, która może się zdarzyć.

  • odpalanie zdarzenia : konkretne wystąpienie zdarzenia; wydarzenie się dzieje.

  • detektor zdarzeń : Coś, co zwraca uwagę na wystrzeliwanie zdarzeń.

  • moduł obsługi zdarzeń : coś, co występuje, gdy detektor zdarzeń wykrywa uruchamianie zdarzenia.

  • subskrybent zdarzenia : odpowiedź, którą ma wywołać procedura obsługi zdarzenia.

Te definicje nie zależą od implementacji, dlatego można je realizować na różne sposoby.

Niektóre z tych terminów są często mylone z synonimami, ponieważ użytkownicy często nie muszą ich rozróżniać.

Typowe scenariusze

  1. Programowanie zdarzeń logicznych.

    • Wydarzenie jest, gdy jakaś metoda jest wywoływana.

    • Wypalania zdarzenie jest szczególnym wezwaniem do tej metody.

    • Detektor zdarzeń jest haczyk w metodzie zdarzeń, który nazywa się na każdym odpaleniem zdarzenia, które wywołuje procedurę obsługi zdarzeń.

    • Moduł obsługi zdarzeń wywołuje kolekcję subskrybentów zdarzenia.

    • Abonent (a) wydarzenie wykonać wszelkie czynności (s) system oznacza wydarzy w odpowiedzi zaistnienia zdarzenia.

  2. Wydarzenia zewnętrzne

    • Wydarzenie jest wydarzeniem zewnętrznym, które można wywieść z obserwabli.

    • Wypalania wydarzenie jest, gdy dzieje, że zewnętrzna może być uznane za mające miejsce.

    • Detektor zdarzeń jakoś wykrywa zapaleń zdarzeń, często przez odpytywanie obserwowalny (s), a następnie wywołuje procedurę obsługi zdarzenia po wykryciu zdarzenia wypalania.

    • Moduł obsługi zdarzeń wywołuje kolekcję subskrybentów zdarzenia.

    • Abonent (a) wydarzenie wykonać wszelkie czynności (s) system oznacza wydarzy w odpowiedzi zaistnienia zdarzenia.

Odpytywanie a wstawianie haków do mechanizmu strzelania zdarzenia

Chodzi o to, że sondaże często nie są konieczne. Wynika to z faktu, że detektory zdarzeń można wdrożyć przez automatyczne wyzwalanie zdarzeń, które jest wywoływane przez procedurę obsługi zdarzeń, co jest często najbardziej wydajnym sposobem implementacji rzeczy, gdy zdarzenia mają miejsce na poziomie systemu.

Analogicznie nie musisz codziennie sprawdzać skrzynki pocztowej, czy pracownik pocztowy puka do twoich drzwi i przekazuje pocztę bezpośrednio do ciebie.

Jednak nasłuchiwanie zdarzeń może również działać przez odpytywanie. Sondowanie niekoniecznie musi sprawdzać określoną wartość lub inną możliwą do zaobserwowania; może być bardziej skomplikowane. Ale ogólnie rzecz biorąc, celem odpytywania jest wnioskowanie, gdy wystąpiło jakieś zdarzenie, na które można zareagować.

Analogicznie, musisz sprawdzać swoją skrzynkę pocztową każdego dnia, gdy pracownik pocztowy po prostu wrzuca do niej pocztę. Nie musiałbyś wykonywać tej ankiety, gdybyś mógł poinstruować pracownika pocztowego, aby zapukał do twoich drzwi, ale często nie jest to możliwe.

Łańcuchowa logika zdarzeń

W wielu językach programowania możesz napisać zdarzenie, które jest wywoływane po naciśnięciu klawisza na klawiaturze lub w określonym czasie. Mimo że są to zdarzenia zewnętrzne, nie trzeba ich odpytywać. Dlaczego?

To dlatego, że system operacyjny odpytuje za ciebie. Na przykład system Windows sprawdza takie rzeczy, jak zmiany stanu klawiatury, a jeśli je wykryje, wywoła subskrybentów zdarzeń. Tak więc, gdy subskrybujesz wydarzenie związane z naciśnięciem klawisza, faktycznie subskrybujesz wydarzenie, które samo w sobie jest subskrybentem wydarzenia, które sonduje.

Analogicznie powiedzmy, że mieszkasz w kompleksie mieszkaniowym, a pracownik poczty wysyła pocztę do wspólnego obszaru odbioru poczty. Następnie pracownik podobny do systemu operacyjnego może sprawdzić tę pocztę dla wszystkich, dostarczając pocztę do mieszkań tych, którzy coś otrzymali. To oszczędza wszystkim innym kłopotów z koniecznością przeszukania obszaru odbioru poczty.


Moja intuicja zakłada, że ​​detektor zdarzeń stale sprawdza, czy zdarzenie zostało uruchomione, co oznacza, że ​​w moim scenariuszu nie będzie inaczej niż sprawdzanie każdej klatki, jeśli zdarzenie zostało uruchomione.

Na podstawie dyskusji w klasie wydaje się, że detektor zdarzeń działa w inny sposób.

Jak działa detektor zdarzeń?

Jak podejrzewasz, zdarzenie może działać poprzez odpytywanie. A jeśli zdarzenie jest w jakiś sposób powiązane z wydarzeniami zewnętrznymi, np. Naciśnięcie klawisza klawiatury, to w pewnym momencie musi nastąpić odpytywanie.

Jest również prawdą, że zdarzenia niekoniecznie muszą obejmować odpytywanie. Na przykład, jeśli zdarzenie ma miejsce po naciśnięciu przycisku, to detektor zdarzenia tego przycisku jest metodą, którą środowisko GUI może wywołać, gdy ustali, że kliknięcie myszą uderzy w przycisk. W tym przypadku nadal trzeba było przeprowadzić odpytywanie, aby można było wykryć kliknięcie myszą, ale detektor myszy jest bardziej pasywnym elementem połączonym z prymitywnym mechanizmem odpytywania poprzez łańcuch zdarzeń.

Aktualizacja: przy odpytywaniu sprzętu na niskim poziomie

Okazuje się, że urządzenia USB i inne nowoczesne protokoły komunikacyjne mają dość fascynujący, podobny do sieci zestaw protokołów interakcji, umożliwiając urządzeniom I / O, w tym klawiaturom i myszom, angażowanie się w topologie ad hoc .

Co ciekawe, „ zakłócenia ” są dość imperatywnymi, synchronicznymi rzeczami, więc nie obsługują topologii sieci ad hoc . Aby to naprawić, „ przerwań ” uogólniono w asynchroniczne pakiety o wysokim priorytecie zwane transakcjami przerwań (w kontekście USB) lub przerwańami sygnalizowanymi komunikatem (w kontekście PCI). Ten protokół jest opisany w specyfikacji USB:

wprowadź opis zdjęcia tutaj

- „ Rysunek 8-31. Maszyna stanu hosta transakcji luzem / kontrolą / przerwaniem OUT ” w „Specyfikacji uniwersalnej magistrali szeregowej, wersja 2.0” , wydrukowana strona-222; PDF-page-250 (2000-04-27)

Istotą wydaje się być to, że urządzenia I / O i komponenty komunikacyjne (takie jak koncentratory USB) w zasadzie działają jak urządzenia sieciowe. Wysyłają więc wiadomości, które wymagają odpytywania portów i tym podobnych. Zmniejsza to zapotrzebowanie na dedykowane linie sprzętowe.

Wydaje się, że systemy operacyjne, takie jak Windows, same obsługują proces odpytywania, np. Jak opisano w dokumentacji MSDN dla tych USB_ENDPOINT_DESCRIPTOR, która opisuje, jak kontrolować, jak często Windows odpytuje kontroler hosta USB w poszukiwaniu komunikatów przerywających / izochronicznych:

bIntervalWartość zawiera interwał sondowania dla przerwań i izochronicznych końcowych. W przypadku innych typów punktu końcowego tę wartość należy zignorować. Ta wartość odzwierciedla konfigurację urządzenia w oprogramowaniu układowym. Kierowcy nie mogą tego zmienić.

Interwał odpytywania wraz z prędkością urządzenia i typem kontrolera hosta określają częstotliwość, z jaką sterownik powinien inicjować przerwanie lub transfer izochroniczny. Wartość w bIntervalnie reprezentuje ustalonego czasu. Jest to wartość względna, a faktyczna częstotliwość odpytywania będzie również zależeć od tego, czy urządzenie i kontroler hosta USB działają z niską, pełną lub wysoką prędkością.

- „Struktura USB_ENDPOINT_DESCRIPTOR” , Hardware Dev Center, Microsoft

Nowsze protokoły połączeń monitora, takie jak DisplayPort, wydają się robić to samo:

Transport wielostrumieniowy (MST)

  • Dodano MST (Multi-Stream Transport) w DisplayPort wer. 1.2

    • Tylko SST (Single-Stream Transport) był dostępny w wersji 1.1a
  • MST przenosi wiele strumieni A / V przez jedno złącze

    • Do 63 strumieni; nie „Stream per Lane”

      • Nie zakłada się synchroniczności między transportowanymi strumieniami; jeden strumień może być wygaszony, podczas gdy inne nie
    • Transport zorientowany na połączenie

      • Ścieżka od źródła strumienia do docelowego ujścia strumienia ustanowionego za pomocą transakcji komunikatów przez AUX CHʼ przed rozpoczęciem transmisji strumienia

      • Dodawanie / usuwanie strumienia bez wpływu na pozostałe strumienie

wprowadź opis zdjęcia tutaj

Slajd nr 14 z „Przeglądu DisplayPortTM wersja 1.2” (06.12.2010)

Ta abstrakcja pozwala na kilka ciekawych funkcji, takich jak uruchamianie 3 monitorów z jednego połączenia:

DisplayPort Multi-Stream Transport pozwala również na połączenie trzech lub więcej urządzeń razem, ale w odwrotnej, mniej zorientowanej na „konsumenta” konfiguracji: jednoczesne sterowanie wieloma wyświetlaczami z jednego portu wyjściowego.

- „DisplayPort” , Wikipedia

Pod względem koncepcyjnym należy oderwać się od tego, że mechanizmy odpytywania pozwalają na bardziej uogólnioną komunikację szeregową, co jest niesamowite, gdy potrzebujesz bardziej ogólnej funkcjonalności. Sprzęt i system operacyjny wykonują więc wiele sondowań dla systemu logicznego. Następnie klienci, którzy subskrybują wydarzenia, mogą cieszyć się szczegółami obsługiwanymi przez system niższego poziomu bez konieczności pisania własnych protokołów odpytywania / przekazywania wiadomości.

Ostatecznie zdarzenia takie jak naciśnięcia klawiszy wydają się przechodzić przez dość interesującą serię zdarzeń, zanim dotrą do imperatywnego mechanizmu wyzwalania zdarzeń na poziomie oprogramowania.


Jeśli chodzi o ostatni akapit, generalnie nie ma odpytywania na niskim poziomie, system operacyjny reaguje na przerwania sprzętowe uruchamiane przez urządzenia peryferyjne. Komputer zwykle ma wiele podłączonych urządzeń (mysz, klawiatura, napędy dysków, karty sieciowe), a odpytywanie wszystkich z nich byłoby bardzo nieefektywne.
Barmar

Jednak twoje analogie do dostarczania poczty są dokładnie tym, jak wyjaśniłbym aktywność wyższego poziomu.
Barmar

1
@Barmar Wiesz, kiedy urządzenia przeniosły się na połączenia USB, dużo się mówiło o tym, jak przeszli od bezpośredniego generowania przerwań (jak robi to klawiatura PS / 2) do wymagania odpytywania (jak robi klawiatura USB), a niektóre źródła twierdzą, że że odpytywanie jest wykonywane przez procesor. Ale inne źródła twierdzą, że odbywa się to na specjalistycznym kontrolerze, który przekształca odpytywanie w przerwanie dla procesora.
Nat

@Barmar Czy wiesz, co jest poprawne? Prawdopodobnie widziałem więcej źródeł twierdzących, że procesor odpytuje procesor niż w innym przypadku, ale wyspecjalizowany kontroler wydaje się mieć większy sens. To znaczy, myślę, że Arduino i inne urządzenia wbudowane zwykle wymagają procesora do przeprowadzenia odpytywania, ale nie wiem o urządzeniach typu x86.
Nat

1
Jeśli ktokolwiek może potwierdzić, że mogę zaktualizować tę odpowiedź, myślę, że nowoczesne urządzenia we / wy, np. Podłączone przez USB, bezpośrednio zapisują w pamięci , omijając kontrolę nad procesorem (zarówno dlatego są szybkie / wydajne, jak i zabezpieczające ryzyko czasami ). Następnie nowoczesny system operacyjny jest wymagany do przeszukania pamięci w celu sprawdzenia nowych wiadomości.
Nat

8

Pull vs Push

Istnieją dwie główne strategie sprawdzania, czy zdarzenie się wydarzyło lub czy osiągnięto określony stan. Na przykład wyobraź sobie, że czekasz na ważną dostawę:

  • Pociągnij : co 10 minut zejdź do skrzynki pocztowej i sprawdź, czy została dostarczona,
  • Push : powiadom dostawcę, aby zadzwonił do ciebie, gdy dokona dostawy.

Metoda ściągania (zwana również odpytywaniem) jest prostsza: możesz ją wdrożyć bez żadnych specjalnych funkcji. Z drugiej strony jest to często mniej wydajne, ponieważ ryzykujesz dodatkowe kontrole bez niczego do pokazania.

Z drugiej strony, metoda wypychania jest ogólnie bardziej wydajna: kod działa tylko wtedy, gdy ma coś do zrobienia. Z drugiej strony wymaga mechanizmu rejestrowania słuchacza / obserwatora / wywołania zwrotnego 1 .

1 Mój listonosz zazwyczaj nie ma takiego mechanizmu, niestety.


1

O jedności w konkretnym przypadku - nie ma innego sposobu sprawdzenia wkładu gracza, niż odpytywanie go w każdej klatce. Aby utworzyć detektor zdarzeń, nadal potrzebujesz obiektu takiego jak „system zdarzeń” lub „menedżer zdarzeń”, aby wykonać odpytywanie, więc tylko popchnęłoby problem do innej klasy.

To prawda, że ​​gdy masz już menedżera zdarzeń, masz tylko jedną klasę odpytującą dane wejściowe w każdej ramce, ale nie daje to żadnych oczywistych korzyści w zakresie wydajności, ponieważ teraz ta klasa musi iterować nad słuchaczami i wywoływać je, które, w zależności od twojej gry projekt (jak w, ile jest nasłuchujących i jak często odtwarzacz wykorzystuje dane wejściowe), może faktycznie być bardziej kosztowny.

Poza tym pamiętajcie o złotej zasadzie - przedwczesna optymalizacja jest źródłem wszelkiego zła , co jest szczególnie prawdziwe w grach wideo, w których często proces renderowania każdej klatki kosztuje tyle, że małe optymalizacje skryptu są zupełnie nieistotne


Nie widziałbym centralnej pętli zdarzeń jako optymalizacji, ale jako pisanie bardziej czytelnego, zrozumiałego kodu, w przeciwieństwie do sondowania rozsianych po całej bazie kodu. Umożliwia także zdarzenia „syntetyczne” i zdarzenia niepochodzące z odpytywania silnika gry.
BlackJack

@BlackJack Zgadzam się i zwykle koduję to w ten sposób, ale OP zapytał o wydajność. Przy okazji, Unity ma zaskakująco wiele podejrzanych decyzji dotyczących projektowania kodu, takich jak posiadanie funkcji statycznych niemal wszędzie.
Dunno

1

Chyba że masz jakieś wsparcie w swoim systemie operacyjnym / frameworku, które obsługuje zdarzenia, takie jak naciśnięcie przycisku lub przepełnienie timera lub nadejście wiadomości - będziesz musiał zaimplementować ten sposób nasłuchiwania zdarzeń za pomocą odpytywania (gdzieś poniżej).

Ale nie odwracaj się od tego wzorca projektowego tylko dlatego, że nie od razu zyskujesz na wydajności. Oto powody, dla których powinieneś go używać bez względu na to, czy masz wsparcie dla obsługi zdarzeń, czy nie.

  1. Kod wygląda na bardziej przejrzysty i bardziej izolowany (oczywiście jeśli jest poprawnie zaimplementowany)
  2. Kod oparty na procedurach obsługi zdarzeń lepiej znosi zmiany (ponieważ zwykle modyfikujesz tylko niektóre procedury obsługi zdarzeń)
  3. Jeśli zdarzy ci się przejść na platformę z obsługą obsługi zdarzeń - możesz ponownie użyć istniejących procedur obsługi zdarzeń i po prostu pozbyć się kodu odpytywania.

Wniosek - miałeś szczęście uczestniczyć w dyskusji i nauczyłeś się jednej alternatywy dla ankiet. Poszukaj okazji do zastosowania tej koncepcji w praktyce, a docenisz, jak elegancki może być kod.


1

Większość pętli zdarzeń jest zbudowanych powyżej prymitywnego multipleksowania z odpytywaniem udostępnianego przez system operacyjny. W Linuksie ta prymityw jest często poll(2) wywołaniem systemowym (ale może być starym select). W aplikacjach GUI serwer wyświetlania (np. Xorg lub Wayland ) komunikuje się (przez gniazdo (7) lub potok (7) ) z twoją aplikacją. Przeczytaj także o protokołach i architekturze systemu X Window .

Takie operacje podstawowe odpytywania są wydajne; jądro w praktyce obudzi Twój proces, gdy zostanie wykonane jakieś wejście (a niektóre przerwania zostaną obsłużone).

Konkretnie, biblioteka narzędzi widgetów komunikuje się z serwerem wyświetlania, czekając na wiadomości i wysyłając te wiadomości do widgetów. Biblioteki zestawów narzędzi, takie jak Qt lub GTK, są dość złożone (miliony linii kodu źródłowego). Klawiatura i mysz są obsługiwane tylko przez proces serwera wyświetlania (który tłumaczy takie dane wejściowe na komunikaty zdarzeń wysyłane do aplikacji klienckich).

(Upraszczam; w rzeczywistości rzeczy są znacznie bardziej złożone)


1

W systemie opartym wyłącznie na sondowaniu podsystem, który może chcieć wiedzieć, kiedy nastąpi określone działanie, będzie musiał uruchomić jakiś kod za każdym razem, gdy może ono nastąpić. Jeśli istnieje wiele podsystemów, z których każdy musiałby zareagować w ciągu 10 ms od wystąpienia niekoniecznie wyjątkowego zdarzenia, wszyscy musieliby sprawdzać co najmniej 100 razy / sekundę, czy ich zdarzenie miało miejsce. Jeśli te podsystemy są w różnych procesach wątkowych (lub, co gorsza, procesach), wymagałoby to przełączania w każdym takim wątku lub procesie 100x / sekundę.

Jeśli wiele rzeczy, na które będą patrzeć aplikacje, jest raczej podobnych, bardziej efektywnym może być scentralizowany podsystem monitoringu - być może sterowany tabelą - który może obserwować wiele rzeczy i obserwować, czy któraś z nich się zmieniła. Jeśli na przykład są 32 przełączniki, platforma może mieć funkcję odczytu wszystkich 32 przełączników jednocześnie w słowo, umożliwiając kodowi monitora sprawdzenie, czy między przełącznikami zmieniły się jakiekolwiek ankiety, a jeśli nie, to nie martw się, jaki kod może być nimi zainteresowany.

Jeśli istnieje wiele podsystemów, które chciałyby powiadamiać, gdy coś się zmieni, dedykowany podsystem monitorowania powiadamia inne podsystemy, gdy wystąpią zdarzenia, które są nimi zainteresowane, mogą być bardziej wydajne niż to, że każdy podsystem sonduje własne zdarzenia. Utworzenie dedykowanego podsystemu monitorowania w przypadkach, w których nikt nie jest zainteresowany żadnymi zdarzeniami, stanowiłoby jednak czystą stratę zasobów. Jeśli istnieje tylko kilka podsystemów, które są zainteresowane zdarzeniami, koszt ich obejrzenia dla wydarzeń, którymi są zainteresowani, może być mniejszy niż koszt utworzenia dedykowanego podsystemu monitorowania ogólnego przeznaczenia, ale próg rentowności punkt różni się znacznie między różnymi platformami.


0

Odbiornik zdarzenia jest jak ucho oczekujące na wiadomość. Po wystąpieniu zdarzenia podprogram wybrany jako detektor zdarzeń działa przy użyciu argumentów zdarzenia.

Zawsze są dwa ważne dane: moment, w którym zdarzenie ma miejsce i obiekt, w którym to zdarzenie ma miejsce. Kolejnym argumentem są dodatkowe dane o tym, co się stało.

Detektor zdarzeń określa reakcję na wystąpienie.


0

Detektor zdarzeń stosuje się do wzorca publikowania / subskrybowania (jako subskrybent)

W najprostszej formie obiekt publikujący przechowuje listę instrukcji subskrybentów, które należy wykonać, gdy trzeba coś opublikować.

Będzie miał jakąś subscribe(x)metodę, gdzie x zależy od tego, jak procedura obsługi zdarzeń jest zaprojektowana do obsługi zdarzenia. Po wywołaniu funkcji subscribe (x) x jest dodawane do listy wydawców instrukcji / referencji subskrybentów.

Wydawca może zawierać całą logikę do obsługi zdarzenia lub jej część. Może po prostu wymagać odwołań do subskrybentów, aby powiadomić ich / przekształcić za pomocą określonej logiki, gdy wystąpi zdarzenie. Może nie zawierać logiki i wymagać obiektów subskrybenta (metod / detektorów zdarzeń), które mogą obsłużyć zdarzenie. Najprawdopodobniej zawiera mieszankę obu.

W przypadku wystąpienia zdarzenia wydawca wykona iterację i wykona logikę dla każdego elementu na liście instrukcji / referencji subskrybentów.

Bez względu na to, jak skomplikowany jest moduł obsługi zdarzeń, u jego podstaw leży ten prosty wzór.

Przykłady

Na przykład detektora zdarzeń podajesz metodę / funkcji / instrukcji / detektora zdarzeń do metody subscribe () procedury obsługi zdarzeń. Procedura obsługi zdarzeń dodaje metodę do swojej listy wywołań zwrotnych subskrybenta. Gdy wystąpi zdarzenie, moduł obsługi zdarzeń wykonuje iterację po liście i wykonuje każde wywołanie zwrotne.

Na przykład w świecie rzeczywistym, kiedy subskrybujesz biuletyn na Stack Exchange, odniesienie do twojego profilu zostanie dodane do tabeli subskrybentów bazy danych. Kiedy nadejdzie czas opublikowania biuletynu, odnośnik zostanie wykorzystany do wypełnienia szablonu biuletynu i zostanie wysłany na Twój e-mail. W tym przypadku x jest po prostu odniesieniem do ciebie, a wydawca ma zestaw instrukcji wewnętrznych używanych dla wszystkich subskrybentów.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.