Làm thế nào để một người nghe sự kiện làm việc?


125

Trong một trong những bài giảng của tôi hôm nay về Unity, chúng tôi đã thảo luận về việc cập nhật vị trí người chơi của chúng tôi bằng cách kiểm tra mọi khung hình nếu người dùng có một nút ấn xuống. Có người nói điều này không hiệu quả và chúng ta nên sử dụng một người nghe sự kiện thay thế.

Câu hỏi của tôi là, bất kể ngôn ngữ lập trình, hoặc tình huống mà nó được áp dụng, một trình lắng nghe sự kiện hoạt động như thế nào?

Trực giác của tôi sẽ cho rằng người nghe sự kiện liên tục kiểm tra xem sự kiện đã bị hủy hay chưa, nghĩa là, trong kịch bản của tôi, nó sẽ không khác gì kiểm tra mọi khung hình nếu sự kiện đã bị bắn.

Dựa trên các cuộc thảo luận trong lớp, có vẻ như người nghe sự kiện hoạt động theo một cách khác.

Làm thế nào để một người nghe sự kiện làm việc?


34
Một người nghe sự kiện không kiểm tra gì cả. Nó được gọi khi sự kiện đang "lắng nghe" với đám cháy.
Robert Harvey

13
Có, nhưng làm thế nào để "lắng nghe", nó sẽ không liên tục kiểm tra?
Gary

28
Không. "Người nghe sự kiện" có lẽ là một lựa chọn từ ngữ kém; nó hoàn toàn không "lắng nghe". Tất cả một người nghe sự kiện làm là chờ đợi để được gọi bởi sự kiện khi nó kích hoạt, giống như bất kỳ phương thức nào khác. Cho đến khi nó được gọi theo cách này, nó không làm gì cả.
Robert Harvey

28
Mỗi lần bạn kiểm tra xem nút có được ấn hay không, bạn sẽ phải trả giá theo chu kỳ. Trình xử lý sự kiện (người nghe) chỉ tốn chi phí khi nút thực sự được ấn.
Robert Harvey

45
@RobertHarvey - không nhất thiết, vì "người nghe" vẫn cần bỏ phiếu liên tục ở cấp độ thấp hơn. Bạn chỉ cần đẩy sự phức tạp từ lớp mã của riêng bạn xuống sâu hơn đến các ngắt phần cứng hoặc bất cứ điều gì. Và vâng, điều này thường sẽ hiệu quả hơn, nhưng không phải vì lắng nghe vượt trội hơn so với bỏ phiếu, bởi vì việc bỏ phiếu ở cấp độ thấp sẽ hiệu quả hơn so với bỏ phiếu từ C # và 15 lớp trừu tượng giữa bạn và phần cứng.
Thưởng thức Ždralo

Câu trả lời:


140

Không giống như ví dụ bỏ phiếu mà bạn cung cấp (trong đó nút được kiểm tra mỗi khung hình), người nghe sự kiện không kiểm tra xem nút có được ấn hay không. Thay vào đó, nó được gọi khi nhấn nút.

Có lẽ thuật ngữ "người nghe sự kiện" đang ném bạn. Thuật ngữ này cho thấy "người nghe" đang tích cực làm gì đó để lắng nghe, trong khi thực tế, nó không làm gì cả. "Người nghe" chỉ là một chức năng hoặc phương thức được đăng ký vào sự kiện. Khi sự kiện kích hoạt, phương thức người nghe ("xử lý sự kiện") được gọi.

Lợi ích của mẫu sự kiện là không có chi phí cho đến khi nút thực sự được đẩy. Sự kiện này có thể được xử lý theo cách này mà không bị theo dõi bởi vì nó bắt nguồn từ cái mà chúng ta gọi là "ngắt phần cứng", trong đó nhanh chóng thử mã chạy để chạy sự kiện.

Một số giao diện người dùng và khung trò chơi sử dụng một cái gì đó gọi là "vòng lặp thông báo", xếp hàng các sự kiện để thực hiện vào một khoảng thời gian sau (thường là ngắn), nhưng bạn vẫn cần một ngắt phần cứng để đưa sự kiện đó vào vòng lặp thông báo ở vị trí đầu tiên.


54
Có thể đáng nói đến lý do không có chi phí cho đến khi nút được nhấn là do các nút "đặc biệt", máy tính bị gián đoạn và các phương tiện đặc biệt khác mà HĐH có thể sử dụng, được trừu tượng hóa trong các ứng dụng không gian người dùng.
tên của

46
@whatsisname trong khi đó là trường hợp rất sâu dưới mui xe, trong thực tế, các công cụ trò chơi có thể không hoạt động với các ngắt, nhưng trên thực tế vẫn đang thăm dò một nguồn sự kiện trong một vòng lặp. Chỉ là việc bỏ phiếu này được tập trung và tối ưu hóa, do đó việc thêm nhiều người nghe sự kiện sẽ không thêm sự bỏ phiếu và sự phức tạp.
gntskn

7
@PieterGeerkens Tôi đoán rằng gntskn có nghĩa là một phần của vòng lặp công cụ trò chơi, có một bước kiểm tra bất kỳ sự kiện nổi bật nào. Các sự kiện sẽ được xử lý trong mỗi vòng lặp cùng với tất cả các hoạt động một lần trên mỗi vòng lặp khác. Sẽ không có một vòng lặp riêng để kiểm tra các sự kiện.
Joshua Taylor

2
@Voo: Tất cả lý do nhiều hơn để không đi vào mức độ chi tiết trong bài viết này.
Robert Harvey

2
@Voo: Tôi đang nói về các nút như các phím vật lý trên bàn phím và nút chuột.
whatsisname

52

Một người nghe sự kiện gần giống với đăng ký bản tin email (bạn tự đăng ký để nhận các bản cập nhật, việc truyền tải sau đó được gửi bởi người gửi), thay vì làm mới vô tận một trang web (nơi bạn là người bắt đầu truyền thông tin).

Một hệ thống sự kiện được triển khai bằng các đối tượng sự kiện, quản lý danh sách các thuê bao. Các đối tượng quan tâm (được gọi là người đăng ký , người nghe , đại biểu , v.v.) có thể đăng ký để được thông báo về một sự kiện bằng cách gọi một phương thức đăng ký chính mình vào sự kiện, khiến sự kiện thêm chúng vào danh sách của nó. Bất cứ khi nào sự kiện được kích hoạt (thuật ngữ cũng có thể bao gồm: được gọi , được kích hoạt , được gọi , chạy , v.v.), nó gọi phương thức thích hợp trên mỗi người đăng ký, để thông báo cho họ về sự kiện, chuyển qua bất kỳ thông tin theo ngữ cảnh nào họ cần hiểu Chuyện gì đã xảy ra.


38

Câu trả lời ngắn gọn, không thỏa đáng là ứng dụng nhận được tín hiệu (sự kiện) và rằng thói quen chỉ được gọi tại thời điểm đó.

Các giải thích dài hơn là một chút liên quan.

Sự kiện khách hàng đến từ đâu?

Mỗi ứng dụng hiện đại có một nội tâm, thường bán ẩn "sự kiện vòng lặp" rằng công văn các sự kiện để các thành phần đúng khi cho rằng nên nhận được chúng. Ví dụ: một sự kiện "nhấp chuột" được gửi đến nút có bề mặt hiển thị ở tọa độ chuột hiện tại. Đây là ở cấp độ đơn giản nhất. Trong thực tế, HĐH thực hiện rất nhiều công việc này vì một số sự kiện và một số thành phần sẽ nhận được tin nhắn trực tiếp.

Sự kiện ứng dụng đến từ đâu?

Hệ điều hành gửi các sự kiện khi chúng xảy ra. Họ làm như vậy một cách phản ứng bằng cách được thông báo bởi trình điều khiển riêng của họ.

Làm thế nào để trình điều khiển tạo sự kiện?

Tôi không phải là một chuyên gia, nhưng chắc chắn một số sử dụng CPU bị gián đoạn: phần cứng mà họ kiểm soát sẽ tăng một chân trên CPU khi có dữ liệu mới; CPU kích hoạt trình điều khiển xử lý dữ liệu đến để tạo ra một sự kiện (hàng đợi) được gửi đi và sau đó trả lại quyền điều khiển cho HĐH.

Vì vậy, như bạn thấy, ứng dụng của bạn không thực sự chạy mọi lúc. Đó là một loạt các thủ tục bị HĐH (sắp xếp) sa thải khi các sự kiện xảy ra, nhưng không có gì còn lại trong thời gian còn lại.


có những ngoại lệ đáng chú ý ví dụ như trò chơi cho một lần mà có thể làm những việc khác nhau


10
Câu trả lời này giải thích tại sao không có cuộc bỏ phiếu nào liên quan đến các sự kiện nhấp chuột trong trình duyệt. Phần cứng tạo ra ngắt => trình điều khiển giải quyết nó thành sự kiện OS => trình duyệt giải quyết nó thành sự kiện DOM => Công cụ JS chạy trình nghe cho sự kiện đó.
Tibos

@Tibos afaict nó cũng áp dụng cho các sự kiện bàn phím, sự kiện hẹn giờ, sự kiện vẽ tranh, v.v.
Sklivvz

19

Thuật ngữ

  • sự kiện : Một loại điều có thể xảy ra.

  • bắn sự kiện : Một sự kiện cụ thể xảy ra; một sự kiện xảy ra

  • người nghe sự kiện : Một cái gì đó trông ra cho sự kiện cháy.

  • xử lý sự kiện : Một cái gì đó xảy ra khi một người nghe sự kiện phát hiện một sự kiện bắn.

  • người đăng ký sự kiện : Phản hồi mà người xử lý sự kiện phải gọi.

Các định nghĩa này không phụ thuộc vào việc thực hiện, vì vậy chúng có thể được thực hiện theo nhiều cách khác nhau.

Một số thuật ngữ này thường bị nhầm với từ đồng nghĩa vì thường không cần người dùng phân biệt giữa chúng.

Kịch bản thường gặp

  1. Sự kiện lập trình-logic.

    • Sự kiện này là khi một số phương thức được gọi.

    • Một sự kiện bắn là một cuộc gọi cụ thể cho phương pháp đó.

    • Trình lắng nghe sự kiện là một cái móc trong phương thức sự kiện được gọi trong mỗi lần phát sinh sự kiện gọi trình xử lý sự kiện.

    • Trình xử lý sự kiện gọi một bộ sưu tập các thuê bao sự kiện.

    • Người đăng ký sự kiện thực hiện bất kỳ hành động nào mà hệ thống có nghĩa là xảy ra để đáp ứng với sự kiện xảy ra.

  2. Các sự kiện bên ngoài.

    • Sự kiện này là một sự kiện bên ngoài có thể được suy ra từ các đài quan sát.

    • Một sự kiện bắn là khi sự kiện bên ngoài đó có thể được công nhận là đã xảy ra.

    • Người nghe sự kiện bằng cách nào đó phát hiện sự kiện cháy, thường bằng cách bỏ phiếu (các) có thể quan sát được, sau đó nó gọi trình xử lý sự kiện khi phát hiện sự kiện đang diễn ra.

    • Trình xử lý sự kiện gọi một bộ sưu tập các thuê bao sự kiện.

    • Người đăng ký sự kiện thực hiện bất kỳ hành động nào mà hệ thống có nghĩa là xảy ra để đáp ứng với sự kiện xảy ra.

Bỏ phiếu so với chèn móc vào cơ chế bắn của sự kiện

Quan điểm của những người khác là việc bỏ phiếu thường không cần thiết. Điều này là do người nghe sự kiện có thể được thực hiện bằng cách tự động gọi sự kiện xử lý sự kiện, đây thường là cách hiệu quả nhất để thực hiện mọi thứ khi sự kiện xảy ra ở cấp hệ thống.

Bằng cách tương tự, bạn không cần kiểm tra hộp thư của mình để nhận thư mỗi ngày nếu nhân viên bưu điện gõ cửa nhà bạn và trao thư trực tiếp cho bạn.

Tuy nhiên, người nghe sự kiện cũng có thể làm việc bằng cách bỏ phiếu. Bỏ phiếu không nhất thiết phải kiểm tra một giá trị cụ thể hoặc có thể quan sát khác; nó có thể phức tạp hơn Nhưng, về tổng thể, điểm bỏ phiếu là suy luận khi một số sự kiện đã xảy ra để nó có thể được phản hồi.

Bằng cách tương tự, bạn phải kiểm tra hộp thư của bạn mỗi ngày khi nhân viên bưu điện chỉ bỏ thư trong đó. Bạn sẽ không phải thực hiện công việc bỏ phiếu này nếu bạn có thể hướng dẫn nhân viên bưu điện gõ cửa nhà bạn, nhưng đó thường không phải là một khả năng.

Chuỗi sự kiện logic

Trong nhiều ngôn ngữ lập trình, bạn có thể viết một sự kiện chỉ được gọi khi nhấn phím trên bàn phím hoặc tại một thời điểm nhất định. Mặc dù đây là những sự kiện bên ngoài, bạn không cần phải thăm dò ý kiến. Tại sao?

Đó là vì hệ điều hành đang bỏ phiếu cho bạn. Ví dụ: Windows kiểm tra các nội dung như thay đổi trạng thái bàn phím và nếu phát hiện ra một thứ, nó sẽ gọi các thuê bao sự kiện. Vì vậy, khi bạn đăng ký một sự kiện nhấn bàn phím, bạn thực sự đang đăng ký một sự kiện mà chính nó là người đăng ký cho một sự kiện bỏ phiếu.

Bằng cách tương tự, giả sử rằng bạn đang sống trong một khu chung cư và một nhân viên bưu điện thả thư vào khu vực nhận thư chung. Sau đó, một nhân viên giống như hệ điều hành có thể kiểm tra thư đó cho mọi người, gửi thư đến căn hộ của những người nhận được thứ gì đó. Điều này tránh cho mọi người những rắc rối khác khi phải thăm dò khu vực nhận thư.


Trực giác của tôi sẽ cho rằng người nghe sự kiện liên tục kiểm tra xem sự kiện đã bị hủy hay chưa, nghĩa là, trong kịch bản của tôi, nó sẽ không khác gì kiểm tra mọi khung hình nếu sự kiện đã bị bắn.

Dựa trên các cuộc thảo luận trong lớp, có vẻ như người nghe sự kiện hoạt động theo một cách khác.

Làm thế nào để một người nghe sự kiện làm việc?

Như bạn đã nghi ngờ, một sự kiện có thể hoạt động thông qua bỏ phiếu. Và nếu một sự kiện nào đó liên quan đến các sự kiện bên ngoài, ví dụ như một phím bàn phím bị nhấn, thì việc bỏ phiếu sẽ phải xảy ra tại một số điểm.

Cũng đúng là các sự kiện không nhất thiết phải liên quan đến việc bỏ phiếu. Ví dụ: nếu sự kiện là khi nhấn nút, thì trình lắng nghe sự kiện của nút đó là phương thức mà khung GUI có thể gọi khi xác định rằng nhấp chuột chạm vào nút. Trong trường hợp này, việc bỏ phiếu vẫn phải xảy ra khi nhấp chuột để phát hiện, nhưng người nghe chuột là một yếu tố thụ động hơn được kết nối với cơ chế bỏ phiếu nguyên thủy thông qua chuỗi sự kiện.

Cập nhật: Về bỏ phiếu phần cứng cấp thấp

Hóa ra các thiết bị USB và các giao thức giao tiếp hiện đại khác có một bộ giao thức tương tự như mạng để thu hút các tương tác, cho phép các thiết bị I / O bao gồm bàn phím và chuột tham gia vào các cấu trúc liên kết ad hoc .

Thật thú vị, " ngắt " là những thứ khá bắt buộc, đồng bộ, vì vậy chúng không xử lý các cấu trúc liên kết mạng ad hoc . Để khắc phục điều này, " ngắt " đã được khái quát thành các gói ưu tiên cao không đồng bộ được gọi là " giao dịch ngắt " (trong ngữ cảnh của USB) hoặc " ngắt tín hiệu tin nhắn " (trong ngữ cảnh của PCI). Giao thức này được mô tả trong thông số kỹ thuật USB:

nhập mô tả hình ảnh ở đây

- " Hình 8-31. Số lượng lớn / Kiểm soát / Ngắt máy trạng thái máy chủ giao dịch " trong "Thông số kỹ thuật bus nối tiếp toàn cầu, phiên bản 2.0" , trang in-222; PDF-trang-250 (2000-04-27)

Ý chính dường như là các thiết bị I / O và các thành phần giao tiếp (như các trung tâm USB) về cơ bản hoạt động như các thiết bị mạng. Vì vậy, họ gửi tin nhắn, yêu cầu bỏ phiếu cổng của họ và như vậy. Điều này làm giảm nhu cầu về các dòng phần cứng chuyên dụng.

Hệ điều hành như Windows dường như xử lý quá trình bỏ phiếu chính nó, ví dụ như mô tả trong tài liệu MSDN cho USB_ENDPOINT_DESCRIPTOR's trong đó mô tả làm thế nào để kiểm soát mức độ thường xuyên của Windows các cuộc thăm dò một bộ điều khiển lưu trữ USB cho thông điệp ngắt / đẳng thời:

Các bIntervalgiá trị có chứa khoảng bỏ phiếu cho các điểm cuối ngắt và đẳng thời. Đối với các loại điểm cuối khác, giá trị này nên được bỏ qua. Giá trị này phản ánh cấu hình của thiết bị trong phần sụn. Trình điều khiển không thể thay đổi nó.

Khoảng thời gian bỏ phiếu, cùng với tốc độ của thiết bị và loại bộ điều khiển máy chủ, xác định tần suất mà trình điều khiển sẽ bắt đầu chuyển giao gián đoạn hoặc chuyển động đẳng thời. Giá trị trong bIntervalkhông đại diện cho một khoảng thời gian cố định. Đó là một giá trị tương đối và tần suất bỏ phiếu thực tế cũng sẽ phụ thuộc vào việc thiết bị và bộ điều khiển máy chủ USB hoạt động ở tốc độ thấp, đầy đủ hay cao.

- "Cấu trúc USB_ENDPOINT_DESCRIPTOR" , Trung tâm phát triển phần cứng, Microsoft

Các giao thức kết nối màn hình mới hơn như DisplayPort dường như cũng làm như vậy:

Vận tải đa luồng (MST)

  • MST (Truyền tải đa luồng) được thêm vào DisplayPort Ver.1.2

    • Chỉ SST (Vận chuyển một luồng) có sẵn trong Ver.1.1a
  • MST vận chuyển nhiều luồng A / V qua một đầu nối

    • Lên đến 63 luồng; không phải Stream Stream trên mỗi Lane Lane

      • Không có sự đồng bộ giả định trong số các luồng vận chuyển; một luồng có thể đang trong giai đoạn trống trong khi các luồng khác thì không
    • Vận chuyển hướng kết nối

      • Đường dẫn từ nguồn phát đến luồng luồng đích được thiết lập thông qua Giao dịch thư qua AUX CHʼ trước khi bắt đầu truyền phát luồng

      • Bổ sung / xóa một luồng mà không ảnh hưởng đến các luồng còn lại

nhập mô tả hình ảnh ở đây

-Slide # 14 từ "Tổng quan về DisplayPortTM Ver.1.2" (2010-12-06)

Sự trừu tượng hóa này cho phép một số tính năng gọn gàng, như chạy 3 màn hình từ một kết nối:

DisplayPort Multi-Stream Transport cũng cho phép kết nối ba hoặc nhiều thiết bị với nhau nhưng ngược lại, cấu hình dựa trên "người tiêu dùng" ít hơn: điều khiển đồng thời nhiều màn hình từ một cổng đầu ra.

- "Cổng hiển thị" , Wikipedia

Về mặt khái niệm, điểm cần tránh khỏi điều này là các cơ chế bỏ phiếu cho phép truyền thông nối tiếp tổng quát hơn, điều này thật tuyệt vời khi bạn muốn có nhiều chức năng chung hơn. Vì vậy, phần cứng và hệ điều hành thực hiện nhiều cuộc bỏ phiếu cho hệ thống logic. Sau đó, người tiêu dùng đăng ký các sự kiện có thể tận hưởng những chi tiết được xử lý cho họ bởi hệ thống cấp thấp hơn mà không phải viết các giao thức bỏ phiếu / chuyển tin nhắn của riêng họ.

Cuối cùng, các sự kiện như bấm phím dường như trải qua một chuỗi các sự kiện khá thú vị trước khi đến cơ chế bắn sự kiện bắt buộc ở cấp độ phần mềm.


Về đoạn cuối của bạn, nhìn chung không có cuộc bỏ phiếu nào được thực hiện ở mức thấp, hệ điều hành phản ứng với các ngắt phần cứng được kích hoạt bởi các thiết bị ngoại vi. Một máy tính thường có nhiều thiết bị được kết nối (chuột, bàn phím, ổ đĩa, card mạng) và việc bỏ phiếu tất cả chúng sẽ rất kém hiệu quả.
Barmar

Tuy nhiên, sự tương tự của bạn với việc gửi thư chính xác là cách tôi sẽ giải thích hoạt động cấp cao hơn.
Barmar

1
@Barmar Ya biết, khi các thiết bị chuyển sang kết nối USB, đã có rất nhiều thảo luận về cách chúng chuyển từ các ngắt trực tiếp (như bàn phím PS / 2) sang yêu cầu bỏ phiếu (như bàn phím USB) và một số nguồn tin khẳng định rằng việc bỏ phiếu được thực hiện bởi CPU. Nhưng, các nguồn khác cho rằng nó được thực hiện trên một bộ điều khiển chuyên dụng chuyển đổi việc bỏ phiếu thành một ngắt cho CPU.
Nat

@Barmar Bạn có biết điều nào đúng không? Có lẽ tôi đã thấy nhiều nguồn tin cho rằng CPU thực hiện việc bỏ phiếu hơn so với cách khác, nhưng một bộ điều khiển chuyên dụng cho nó dường như có ý nghĩa hơn. Ý tôi là, tôi nghĩ rằng Arduino và các thiết bị nhúng khác có xu hướng yêu cầu CPU thực hiện việc bỏ phiếu, nhưng tôi không biết về các thiết bị loại x86.
Nat

1
Nếu bất cứ ai cũng có thể xác nhận để tôi có thể cập nhật câu trả lời này, tôi nghĩ rằng các thiết bị I / O hiện đại, ví dụ như các thiết bị được kết nối bằng USB, ghi trực tiếp vào bộ nhớ , bỏ qua điều khiển của CPU (đó là lý do tại sao chúng nhanh / hiệu quả và bảo mật nguy hiểm đôi khi ). Sau đó, cần có một hệ điều hành hiện đại để thăm dò bộ nhớ để kiểm tra tin nhắn mới.
Nat

8

Kéo vs đẩy

Có hai chiến lược chính để kiểm tra xem một sự kiện đã xảy ra hay đạt đến một trạng thái cụ thể. Ví dụ, hãy tưởng tượng chờ đợi một giao hàng quan trọng:

  • Kéo : cứ sau 10 phút, đi xuống hộp thư của bạn và kiểm tra xem nó đã được gửi chưa,
  • Đẩy : nói với người giao hàng gọi cho bạn khi họ thực hiện giao hàng.

Cách tiếp cận kéo (còn gọi là bỏ phiếu) đơn giản hơn: bạn có thể thực hiện nó mà không cần bất kỳ tính năng đặc biệt nào. Mặt khác, nó thường kém hiệu quả hơn vì bạn có nguy cơ thực hiện kiểm tra thêm mà không có gì để hiển thị cho họ.

Mặt khác, cách tiếp cận đẩy thường hiệu quả hơn: mã của bạn chỉ chạy khi có việc cần làm. Mặt khác, nó yêu cầu một cơ chế tồn tại để bạn đăng ký người nghe / người quan sát / gọi lại 1 .

1 người đưa thư của tôi là thường thiếu một cơ chế như vậy, không may.


1

Về sự thống nhất cụ thể - không có cách nào khác để kiểm tra đầu vào của người chơi ngoài việc bỏ phiếu cho mọi khung hình. Để tạo một trình lắng nghe sự kiện, bạn vẫn sẽ cần một đối tượng như "hệ thống sự kiện" hoặc "trình quản lý sự kiện" để thực hiện bỏ phiếu, do đó, nó sẽ chỉ đẩy vấn đề sang một lớp khác.

Cấp, một khi bạn có một người quản lý sự kiện, bạn chỉ có một lớp bỏ phiếu đầu vào mỗi khung, nhưng điều này không mang lại bất kỳ lợi thế hiệu suất rõ ràng nào, vì bây giờ lớp này phải lặp lại qua người nghe và gọi chúng, tùy thuộc vào trò chơi của bạn thiết kế (như trong, có bao nhiêu người nghe ở đó và tần suất người chơi sử dụng đầu vào), thực sự có thể tốn kém hơn.

Ngoài tất cả những điều này, hãy nhớ quy tắc vàng - tối ưu hóa sớm là gốc rễ của mọi tội lỗi , điều này đặc biệt đúng trong các trò chơi video, nơi thường quá trình kết xuất mỗi khung hình tốn kém rất nhiều, rằng tối ưu hóa kịch bản nhỏ như thế này là hoàn toàn không đáng kể


Tôi sẽ không xem một vòng lặp sự kiện trung tâm là tối ưu hóa nhưng khi viết mã dễ đọc hơn, dễ hiểu hơn so với bỏ phiếu lan truyền khắp cơ sở mã. Nó cũng cho phép các sự kiện và sự kiện tổng hợp của người Viking không đến từ việc bỏ phiếu cho công cụ trò chơi.
BlackJack

@BlackJack Tôi đồng ý và tôi thường tự viết mã theo cách này, nhưng OP đã hỏi về hiệu suất. Btw, Unity đáng ngạc nhiên có nhiều quyết định thiết kế mã đáng ngờ như thế này, giống như có các chức năng tĩnh hầu như ở mọi nơi.
Dunno

1

Trừ khi bạn có một số hỗ trợ trong HĐH / Khung xử lý các sự kiện như nhấn nút hoặc tràn bộ đếm thời gian hoặc đến tin nhắn - bạn sẽ phải triển khai trình tạo Trình lắng nghe sự kiện này bằng cách sử dụng bỏ phiếu (ở đâu đó bên dưới).

Nhưng đừng quay lưng lại với mẫu thiết kế này chỉ vì bạn không có lợi ích hiệu suất ngay lập tức. Dưới đây là những lý do tại sao bạn nên sử dụng nó bất kể bạn có hỗ trợ cho việc xử lý sự kiện hay không.

  1. Mã trông sạch hơn và tách biệt hơn (tất nhiên nếu được triển khai chính xác)
  2. Mã dựa trên trình xử lý sự kiện thay đổi trạng thái tốt hơn (vì bạn thường chỉ sửa đổi một số trình xử lý sự kiện)
  3. Nếu bạn tình cờ chuyển sang nền tảng với sự hỗ trợ của sự kiện - bạn có thể sử dụng lại các trình xử lý sự kiện hiện có của mình và loại bỏ mã bỏ phiếu.

Kết luận - bạn đã may mắn tham gia vào cuộc thảo luận và học được một phương án để bỏ phiếu. Tìm kiếm một cơ hội để áp dụng khái niệm này trong thực tế và bạn sẽ đánh giá cao sự thanh lịch của mã.


1

Hầu hết các vòng lặp sự kiện được xây dựng trên một số nguyên tắc ghép kênh bỏ phiếu được cung cấp bởi hệ điều hành. Trên Linux, nguyên thủy đó thường là poll(2) cuộc gọi hệ thống (nhưng có thể là cuộc gọi cũ select). Trong các ứng dụng GUI, máy chủ hiển thị (ví dụ Xorg hoặc Wayland ) đang liên lạc (thông qua một ổ cắm (7) hoặc ống (7) ) với ứng dụng của bạn. Đọc thêm về Giao thức và Kiến trúc Hệ thống X Window .

Nguyên thủy bỏ phiếu như vậy là hiệu quả; hạt nhân trong thực tế sẽ đánh thức quá trình của bạn khi một số đầu vào được thực hiện (và một số ngắt được xử lý).

Cụ thể, thư viện bộ công cụ widget của bạn giao tiếp với máy chủ hiển thị của bạn, chờ tin nhắn và gửi những tin nhắn này đến widget của bạn. Các thư viện bộ công cụ như Qt hoặc GTK khá phức tạp (hàng triệu dòng mã nguồn). Bàn phím và chuột của bạn chỉ được xử lý bởi quy trình máy chủ hiển thị (dịch các đầu vào đó thành các thông báo sự kiện được gửi đến ứng dụng khách).

(Tôi đang đơn giản hóa; thực tế mọi thứ phức tạp hơn nhiều)


1

Trong một hệ thống dựa trên bỏ phiếu thuần túy, hệ thống con có thể muốn biết khi nào một số hành động cụ thể xảy ra sẽ cần phải chạy một số mã bất cứ khi nào hành động đó có thể xảy ra. Nếu có nhiều hệ thống con mà mỗi hệ thống sẽ cần phản ứng trong vòng 10ms một số sự kiện không nhất thiết phải xảy ra, tất cả chúng sẽ cần kiểm tra ít nhất 100 lần / giây xem sự kiện của chúng có xảy ra hay không. Nếu các hệ thống con đó nằm trong các quy trình khác nhau (hoặc tệ hơn là các quy trình), thì sẽ yêu cầu chuyển đổi trong mỗi luồng như vậy hoặc xử lý 100x / giây.

Nếu nhiều thứ mà các ứng dụng sẽ theo dõi khá giống nhau, thì có thể hiệu quả hơn khi có một hệ thống con giám sát tập trung - có thể là bảng điều khiển - có thể theo dõi nhiều thứ và quan sát xem có bất kỳ thay đổi nào trong số chúng đã thay đổi hay không. Ví dụ, nếu có 32 công tắc, một nền tảng có thể có chức năng đọc tất cả 32 công tắc cùng một lúc thành một từ, giúp mã màn hình có thể kiểm tra xem có bất kỳ công tắc nào đã thay đổi giữa các cuộc thăm dò hay không - nếu không - không lo lắng về những gì mã có thể quan tâm đến họ.

Nếu có nhiều hệ thống con muốn thông báo khi có gì đó thay đổi, việc có một hệ thống con giám sát chuyên dụng sẽ thông báo cho các hệ thống con khác khi các sự kiện xảy ra mà chúng quan tâm có thể hiệu quả hơn so với việc mỗi hệ thống con thăm dò các sự kiện của chính nó. Tuy nhiên, việc thiết lập một hệ thống con giám sát chuyên dụng trong trường hợp không ai quan tâm đến bất kỳ sự kiện nào, sẽ gây ra sự lãng phí tài nguyên thuần túy. Nếu chỉ có một vài hệ thống con quan tâm đến các sự kiện, thì chi phí để chúng theo dõi các sự kiện mà chúng quan tâm có thể thấp hơn chi phí thiết lập một hệ thống con giám sát chuyên dụng cho mục đích chung, nhưng hòa vốn điểm sẽ thay đổi đáng kể giữa các nền tảng khác nhau.


0

Một người nghe sự kiện giống như một tai chờ tin nhắn. Khi sự kiện xảy ra, chương trình con được chọn làm trình lắng nghe sự kiện hoạt động bằng cách sử dụng các đối số sự kiện.

Luôn có hai dữ liệu quan trọng: thời điểm xảy ra sự kiện và đối tượng nơi sự kiện này xảy ra. Đối số khác là dữ liệu nhiều hơn về những gì đã xảy ra.

Người nghe sự kiện chỉ định phản ứng cho điều đó xảy ra.


0

Trình lắng nghe sự kiện tuân theo Mẫu xuất bản / Đăng ký (với tư cách là người đăng ký)

Ở dạng đơn giản nhất, một đối tượng xuất bản duy trì một danh sách các hướng dẫn của người đăng ký sẽ được thực hiện khi cần phải xuất bản một cái gì đó.

Nó sẽ có một loại subscribe(x)phương thức, trong đó x phụ thuộc vào cách xử lý sự kiện được thiết kế để xử lý sự kiện. Khi đăng ký (x) được gọi, x được thêm vào danh sách hướng dẫn / tham chiếu của nhà xuất bản.

Nhà xuất bản có thể chứa tất cả, một số hoặc không logic nào để xử lý sự kiện. Nó có thể chỉ cần yêu cầu tham chiếu đến các thuê bao để thông báo / biến đổi chúng với logic được chỉ định khi sự kiện xảy ra. Nó có thể không chứa logic và yêu cầu các đối tượng thuê bao (phương thức / trình lắng nghe sự kiện) có thể xử lý sự kiện. Nó rất có thể chứa một hỗn hợp của cả hai.

Khi một sự kiện xảy ra, nhà xuất bản sẽ lặp đi lặp lại và thực hiện logic của nó cho từng mục trong danh sách hướng dẫn / tham chiếu của người đăng ký.

Cho dù trình xử lý sự kiện trông phức tạp đến mức nào, thì cốt lõi của nó vẫn tuân theo mô hình đơn giản này.

Ví dụ

Đối với một ví dụ về trình lắng nghe sự kiện, bạn cung cấp một phương thức / hàm / hướng dẫn / trình nghe sự kiện cho phương thức subscribe () của trình xử lý sự kiện. Trình xử lý sự kiện thêm phương thức vào danh sách các cuộc gọi lại thuê bao của nó. Khi một sự kiện xảy ra, trình xử lý sự kiện lặp lại danh sách của nó và thực hiện mỗi cuộc gọi lại.

Đối với một ví dụ trong thế giới thực, khi bạn đăng ký bản tin trên Stack Exchange, một tham chiếu đến hồ sơ của bạn sẽ được thêm vào bảng cơ sở dữ liệu của những người đăng ký. Khi đến lúc xuất bản bản tin, tài liệu tham khảo sẽ được sử dụng để điền vào mẫu bản tin và nó sẽ được gửi đến email của bạn. Trong trường hợp này, x chỉ đơn giản là một tài liệu tham khảo cho bạn và nhà xuất bản có một bộ hướng dẫn nội bộ được sử dụng cho tất cả các thuê bao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.