Khi nào việc bỏ phiếu cho các sự kiện sẽ tốt hơn là sử dụng mẫu quan sát viên?


41

Có kịch bản nào mà việc bỏ phiếu cho các sự kiện sẽ tốt hơn so với sử dụng mẫu quan sát viên không? Tôi có nỗi sợ sử dụng bỏ phiếu và sẽ chỉ bắt đầu sử dụng nếu ai đó đưa cho tôi một kịch bản hay. Tất cả những gì tôi có thể nghĩ là làm thế nào mô hình quan sát tốt hơn bỏ phiếu. Xem xét kịch bản này:

Bạn đang lập trình một trình giả lập xe hơi. Chiếc xe là một đối tượng. Ngay khi xe bật, bạn muốn phát một clip âm thanh "vroom vroom".

Bạn có thể mô hình hóa điều này theo hai cách:

Bỏ phiếu : Thăm dò đối tượng ô tô mỗi giây để xem nó có bật không. Khi bật, hãy phát clip âm thanh.

Mẫu quan sát : Làm cho chiếc xe trở thành Chủ đề của mẫu quan sát viên. Có nó xuất bản sự kiện "bật" cho tất cả các nhà quan sát khi nó bật. Tạo một đối tượng âm thanh mới nghe xe. Yêu cầu nó thực hiện cuộc gọi lại "bật", phát đoạn âm thanh.

Trong trường hợp này, tôi nghĩ rằng mô hình quan sát chiến thắng. Thứ nhất, bỏ phiếu là bộ xử lý chuyên sâu hơn. Thứ hai, clip âm thanh không kích hoạt ngay lập tức khi xe bật. Có thể có khoảng cách lên tới 1 giây vì thời gian bỏ phiếu.


Tôi có thể nghĩ về hầu như không có kịch bản. Mẫu quan sát là những gì thực sự ánh xạ đến thế giới thực và đời thực. Vì vậy, tôi nghĩ rằng không có kịch bản nào sẽ biện minh cho việc không sử dụng nó.
Saeed Neamati

Bạn đang nói về các sự kiện giao diện người dùng , hoặc các sự kiện nói chung?
Bryan Oakley

3
Ví dụ của bạn không loại bỏ vấn đề bỏ phiếu / quan sát. Bạn chỉ đơn giản là chuyển nó xuống cấp thấp hơn. Chương trình của bạn vẫn cần phải tìm hiểu xem chiếc xe có bật hay không theo cơ chế nào đó.
Dunk

Câu trả lời:


55

Hãy tưởng tượng bạn muốn được thông báo về mọi chu kỳ động cơ, ví dụ như để hiển thị phép đo RPM cho người lái xe.

Mẫu quan sát viên: Công cụ xuất bản một sự kiện "chu kỳ động cơ" cho tất cả các quan sát viên cho mỗi chu kỳ. Tạo một trình nghe đếm các sự kiện và cập nhật màn hình RPM.

Thăm dò ý kiến: Màn hình RPM hỏi động cơ theo định kỳ cho bộ đếm chu kỳ động cơ và cập nhật màn hình RPM tương ứng.

Trong trường hợp này, mẫu người quan sát có thể sẽ mất: chu trình động cơ là một quá trình ưu tiên cao, tần suất cao, bạn không muốn trì hoãn hoặc trì hoãn quá trình đó chỉ để cập nhật màn hình. Bạn cũng không muốn phá vỡ nhóm luồng với các sự kiện chu trình động cơ.


PS: Tôi cũng sử dụng mẫu bỏ phiếu thường xuyên trong lập trình phân tán:

Mẫu quan sát viên: Quá trình A gửi tin nhắn đến tiến trình B có nội dung "mỗi lần xảy ra sự kiện E, hãy gửi tin nhắn đến Quy trình A".

Mẫu bỏ phiếu: Quá trình A thường xuyên gửi tin nhắn đến quy trình B có nội dung "nếu bạn xảy ra sự kiện E kể từ lần cuối tôi bỏ phiếu, hãy gửi cho tôi một tin nhắn ngay bây giờ".

Mẫu bỏ phiếu tạo ra tải mạng nhiều hơn một chút. Nhưng mẫu quan sát cũng có nhược điểm:

  • Nếu quá trình A gặp sự cố, nó sẽ không bao giờ hủy đăng ký và quá trình B sẽ cố gắng gửi thông báo cho nó mãi mãi, trừ khi nó có thể phát hiện ra các lỗi quy trình từ xa một cách đáng tin cậy (không phải là một điều dễ dàng)
  • Nếu sự kiện E rất thường xuyên và / hoặc thông báo mang nhiều dữ liệu, thì quá trình A có thể nhận được nhiều thông báo sự kiện hơn mức có thể xử lý. Với mô hình bỏ phiếu, nó chỉ có thể điều tiết việc bỏ phiếu.
  • Trong mẫu quan sát, tải cao có thể gây ra "gợn sóng" trong toàn bộ hệ thống. Nếu bạn sử dụng chặn ổ cắm, những gợn sóng này có thể đi cả hai chiều.

1
Điểm tốt. Đôi khi, tốt hơn là bình chọn vì lợi ích của hiệu suất.
Falcon

1
Số lượng người quan sát dự kiến ​​cũng là một cân nhắc. Khi bạn mong đợi một số lượng lớn các nhà quan sát, việc cập nhật tất cả từ quan sát có thể trở thành một nút cổ chai hiệu suất. Sau đó, dễ dàng hơn nhiều chỉ cần viết một giá trị ở đâu đó và yêu cầu "người quan sát" kiểm tra giá trị đó khi họ cần.
Marjan Venema

1
"trừ khi nó có thể phát hiện các lỗi quy trình từ xa một cách đáng tin cậy (không phải là điều dễ làm)" ... ngoại trừ bằng cách bỏ phiếu; P. Do đó, thiết kế tốt nhất là giảm thiểu phản ứng "không có gì thay đổi" càng nhiều càng tốt. +1, câu trả lời tốt.
pdr

2
@Jojo: Bạn có thể, vâng, nhưng sau đó bạn đang đưa chính sách sẽ thuộc về màn hình vào bộ đếm RPM. Có lẽ người dùng thỉnh thoảng muốn có màn hình RPM có độ chính xác cao.
Zan Lynx

2
@JoJo: Xuất bản mỗi sự kiện thứ 100 là một hack. Nó chỉ hoạt động tốt nếu tần suất sự kiện luôn ở trong phạm vi phù hợp, nếu xử lý sự kiện không mất quá nhiều thời gian cho động cơ, nếu tất cả các thuê bao cần độ chính xác tương đương. Và phải mất một hoạt động mô-đun trên mỗi RPM, mà (giả sử vài nghìn RPM) sẽ làm việc cho CPU nhiều hơn so với một vài thao tác bỏ phiếu mỗi giây.
nikie

7

Bỏ phiếu sẽ tốt hơn nếu quá trình bỏ phiếu chạy chậm hơn đáng kể so với những điều mà nó bỏ phiếu. Nếu bạn đang viết các sự kiện vào cơ sở dữ liệu, tốt hơn hết là nên thăm dò ý kiến ​​của tất cả các nhà sản xuất sự kiện của bạn, thu thập tất cả các sự kiện đã xảy ra kể từ cuộc thăm dò cuối cùng, sau đó viết chúng trong một giao dịch. Nếu bạn đã cố gắng viết mọi sự kiện khi nó xảy ra, bạn có thể không theo kịp và cuối cùng sẽ gặp vấn đề khi hàng đợi đầu vào của bạn bị lấp đầy. Nó cũng có ý nghĩa hơn trong các hệ thống phân tán kết hợp lỏng lẻo, trong đó độ trễ cao hoặc thiết lập kết nối và phá hỏng rất tốn kém. Tôi thấy các hệ thống bỏ phiếu dễ viết và hiểu hơn, nhưng trong hầu hết các tình huống, các nhà quan sát hoặc người tiêu dùng theo sự kiện dường như cung cấp hiệu suất tốt hơn (theo kinh nghiệm của tôi).


7

Việc bỏ phiếu dễ dàng hơn rất nhiều để làm việc qua mạng khi các kết nối có thể bị lỗi, máy chủ có thể bị hỏng, v.v ... Hãy nhớ vào cuối ngày, một ổ cắm TCP cần các tin nhắn lưu giữ trực tiếp, nếu không thì máy chủ sẽ giả định máy khách đã ra đi.

Thăm dò ý kiến ​​cũng tốt khi bạn muốn cập nhật giao diện người dùng, nhưng các đối tượng cơ bản thay đổi rất nhanh , không có điểm nào cập nhật giao diện người dùng nhiều hơn một vài lần một giây trong hầu hết các ứng dụng.

Với điều kiện máy chủ có thể phản hồi, không thay đổi, với chi phí rất thấp và bạn không bỏ phiếu quá thường xuyên và bạn không có 1000 khách hàng bỏ phiếu, sau đó bỏ phiếu hoạt động rất tốt trong cuộc sống thực.

Tuy nhiên, đối với các bộ nhớ trong các trường hợp bộ nhớ , tôi mặc định sử dụng mẫu quan sát viên vì nó thường là công việc ít nhất.


5

Bỏ phiếu có một số nhược điểm, về cơ bản bạn đã nêu chúng trong câu hỏi của bạn.

Tuy nhiên, nó có thể là một giải pháp tốt hơn, khi bạn muốn thực sự tách rời những gì có thể quan sát được từ bất kỳ nhà quan sát nào. Nhưng đôi khi có thể tốt hơn để sử dụng một trình bao bọc có thể quan sát cho đối tượng được quan sát trong các trường hợp như vậy.

Tôi chỉ sử dụng bỏ phiếu khi không thể quan sát được bằng các tương tác đối tượng, thường là trường hợp khi truy vấn cơ sở dữ liệu chẳng hạn, nơi bạn không thể có cuộc gọi lại. Một vấn đề khác có thể là đa luồng, trong đó thường an toàn hơn khi thăm dò ý kiến ​​và xử lý tin nhắn thay vì gọi trực tiếp các đối tượng, để tránh các vấn đề tương tranh.


Tôi không chắc chắn tại sao bạn tin rằng bỏ phiếu là an toàn hơn cho đa luồng. Trong hầu hết các trường hợp, đây sẽ không phải là trường hợp. Khi người xử lý cuộc thăm dò nhận được yêu cầu thăm dò ý kiến, họ phải tìm ra trạng thái của đối tượng được thăm dò, nếu đối tượng đang ở giữa cập nhật, thì nó không an toàn cho người xử lý cuộc thăm dò. Trong kịch bản người nghe, bạn chỉ nhận được thông báo nếu trình đẩy ở trạng thái nhất quán, do đó bạn có thể tránh được hầu hết các sự cố đồng bộ hóa trong đối tượng được hỏi.
Lie Ryan

4

Để có một ví dụ tốt về việc bỏ phiếu từ thông báo, hãy nhìn vào ngăn xếp mạng của hệ điều hành.

Đó là một vấn đề lớn đối với Linux khi ngăn xếp mạng kích hoạt NAPI, API mạng cho phép các trình điều khiển chuyển từ chế độ ngắt (thông báo) sang chế độ bỏ phiếu.

Với nhiều giao diện Ethernet gigabit, các ngắt thường làm quá tải CPU, khiến hệ thống chạy chậm hơn so với yêu cầu. Với việc bỏ phiếu, các card mạng thu thập các gói trong bộ đệm cho đến khi được thăm dò hoặc các thẻ thậm chí ghi các gói vào bộ nhớ thông qua DMA. Sau đó, khi hệ điều hành sẵn sàng, nó sẽ bỏ phiếu cho tất cả dữ liệu của nó và xử lý TCP / IP tiêu chuẩn.

Chế độ bỏ phiếu cho phép CPU thu thập dữ liệu Ethernet ở tốc độ xử lý tối đa mà không cần tải vô dụng. Chế độ ngắt cho phép CPU không hoạt động giữa các gói khi công việc không quá bận rộn.

Bí quyết là khi chuyển từ chế độ này sang chế độ khác. Mỗi chế độ có lợi thế và nên được sử dụng ở nơi thích hợp.


2

Tôi thích bỏ phiếu! Tôi phải không Vâng! Tôi phải không Vâng! Tôi phải không Vâng! Tôi còn không Vâng! Bây giờ thì sao? Vâng!

Như những người khác đã đề cập, nó có thể cực kỳ kém hiệu quả nếu bạn bỏ phiếu chỉ để nhận lại trạng thái không thay đổi lặp đi lặp lại. Đó là một công thức để đốt cháy chu kỳ CPU và rút ngắn đáng kể thời lượng pin trên thiết bị di động. Tất nhiên sẽ không lãng phí nếu bạn trở lại trạng thái mới và có ý nghĩa mỗi lần với tốc độ không nhanh hơn mong muốn.

Nhưng lý do chính khiến tôi thích bỏ phiếu là vì tính đơn giản và tính dễ đoán của nó. Bạn có thể theo dõi thông qua mã và dễ dàng xem khi nào và nơi mọi thứ sẽ xảy ra, và trong chuỗi nào. Nếu, về mặt lý thuyết, chúng ta sống trong một thế giới mà việc bỏ phiếu là một sự lãng phí không đáng kể (mặc dù thực tế cách xa nó), thì tôi tin rằng nó sẽ đơn giản hóa việc duy trì mã rất nhiều. Và đó là lợi ích của việc bỏ phiếu và kéo như tôi thấy nếu chúng ta có thể coi thường hiệu suất, mặc dù chúng ta không nên trong trường hợp này.

Khi tôi bắt đầu lập trình trong kỷ nguyên DOS, các trò chơi nhỏ của tôi xoay quanh việc bỏ phiếu. Tôi đã sao chép một số mã lắp ráp từ một cuốn sách mà tôi hầu như không hiểu liên quan đến các ngắt bàn phím và làm cho nó lưu trữ một bộ đệm của các trạng thái bàn phím, tại đó vòng lặp chính của tôi luôn luôn bỏ phiếu. Là phím lên xuống? Không. Là phím lên xuống? Không. Làm thế nào bây giờ? Không. Hiện nay? Vâng. Được rồi, di chuyển người chơi.

Và trong khi vô cùng lãng phí, tôi thấy rằng lý do dễ dàng hơn nhiều so với những ngày lập trình đa tác vụ và hướng sự kiện. Tôi biết chính xác thời gian và mọi thứ sẽ xảy ra mọi lúc và dễ dàng hơn để giữ tốc độ khung hình ổn định và có thể dự đoán được mà không có trục trặc.

Vì vậy, kể từ đó, tôi đã luôn cố gắng tìm cách để có được một số lợi ích và dự đoán về điều đó mà không thực sự đốt cháy chu kỳ CPU, như sử dụng các biến điều kiện để thông báo cho các luồng để đánh thức trạng thái mới, tại đó chúng có thể kéo trạng thái mới, làm việc của họ, và quay trở lại giấc ngủ để được thông báo lại.

Và bằng cách nào đó tôi thấy hàng đợi sự kiện dễ dàng hơn rất nhiều để làm việc với ít nhất là các mẫu quan sát, mặc dù chúng vẫn không dễ dự đoán nơi bạn sẽ đến hoặc điều gì sẽ xảy ra. Họ ít nhất tập trung luồng điều khiển xử lý sự kiện đến một vài khu vực chính trong hệ thống và luôn xử lý các sự kiện đó trong cùng một luồng thay vì chuyển từ một chức năng sang một nơi hoàn toàn xa xôi và bất ngờ bên ngoài luồng xử lý sự kiện trung tâm. Vì vậy, sự phân đôi không phải luôn luôn nằm giữa người quan sát và bỏ phiếu. Hàng đợi sự kiện là một loại trung gian ở đó.

Nhưng vâng, bằng cách nào đó tôi thấy dễ dàng hơn nhiều để lý luận về các hệ thống thực hiện những thứ gần giống với loại luồng kiểm soát dự đoán mà tôi từng có khi tôi bỏ phiếu từ lâu, trong khi chỉ chống lại xu hướng công việc xảy ra tại lần khi không có thay đổi trạng thái đã xảy ra. Vì vậy, sẽ có lợi nếu bạn có thể làm điều đó theo cách không đốt cháy chu kỳ CPU một cách không cần thiết như với các biến điều kiện.

Vòng lặp đồng nhất

Được rồi, tôi đã nhận được một nhận xét tuyệt vời từ Josh Caswellđó chỉ ra một số sự ngu ngốc trong câu trả lời của tôi:

"như sử dụng các biến điều kiện để thông báo cho các chủ đề thức dậy" Âm thanh giống như sự sắp xếp dựa trên sự kiện / người quan sát, không bỏ phiếu

Về mặt kỹ thuật, chính biến điều kiện đang áp dụng mô hình quan sát để đánh thức / thông báo các luồng, do đó, để gọi rằng "bỏ phiếu" có thể sẽ gây hiểu nhầm đáng kinh ngạc. Nhưng tôi thấy nó mang lại một lợi ích tương tự mà tôi đã tìm thấy khi bỏ phiếu từ thời DOS (chỉ xét về lưu lượng kiểm soát và khả năng dự đoán). Tôi sẽ cố gắng giải thích nó tốt hơn.

Điều tôi thấy hấp dẫn trở lại trong những ngày đó là bạn có thể nhìn vào một phần của mã hoặc truy tìm nó và nói: "Được rồi, toàn bộ phần này được dành riêng để xử lý các sự kiện bàn phím. Không có gì khác sẽ xảy ra trong phần mã này Và tôi biết chính xác những gì sẽ xảy ra trước đó và tôi biết chính xác những gì sẽ xảy ra sau đó (vật lý và kết xuất, ví dụ). " Việc bỏ phiếu của các trạng thái bàn phím đã cho bạn loại tập trung của luồng điều khiển cho đến khi xử lý những gì sẽ diễn ra để đáp ứng với sự kiện bên ngoài này. Chúng tôi đã không đáp ứng với sự kiện bên ngoài này ngay lập tức. Chúng tôi trả lời nó một cách thuận tiện.

Khi chúng tôi sử dụng hệ thống dựa trên đẩy dựa trên mẫu Người quan sát, chúng tôi thường mất những lợi ích đó. Một điều khiển có thể được thay đổi kích thước mà kích hoạt một sự kiện thay đổi kích thước. Khi chúng tôi theo dõi thông qua nó, chúng tôi thấy chúng tôi nằm trong sự kiểm soát kỳ lạ, có rất nhiều điều tùy chỉnh trong việc thay đổi kích thước của nó sẽ kích hoạt nhiều sự kiện hơn. Chúng tôi cuối cùng đã hoàn toàn bất ngờ truy tìm tất cả các sự kiện xếp tầng này như là nơi chúng tôi kết thúc trong hệ thống. Hơn nữa, chúng ta có thể thấy rằng tất cả những điều này thậm chí không xảy ra nhất quán trong bất kỳ luồng đã cho nào bởi vì luồng A có thể thay đổi kích thước điều khiển ở đây trong khi luồng B cũng thay đổi kích thước điều khiển sau này. Vì vậy, tôi luôn thấy điều này rất khó để suy luận về việc khó dự đoán mọi thứ xảy ra cũng như những gì sẽ xảy ra.

Lý do hàng đợi sự kiện đơn giản hơn một chút đối với tôi vì nó đơn giản hóa nơi tất cả những điều này xảy ra ít nhất ở cấp độ luồng. Tuy nhiên, nhiều điều khác nhau có thể xảy ra. Một hàng đợi sự kiện có thể chứa một hỗn hợp các sự kiện chiết trung để xử lý và mỗi người vẫn có thể làm chúng ta ngạc nhiên về dòng thác các sự kiện đã xảy ra, thứ tự chúng được xử lý và cách chúng ta kết thúc ở mọi nơi trong cơ sở mã .

Những gì tôi đang xem xét "gần nhất" với việc bỏ phiếu sẽ không sử dụng hàng đợi sự kiện nhưng sẽ trì hoãn một kiểu xử lý rất đồng nhất. Người PaintSystemta có thể được cảnh báo thông qua một biến điều kiện có công việc vẽ để làm lại một số ô lưới nhất định của cửa sổ, tại đó, nó thực hiện một vòng tuần tự đơn giản thông qua các ô và sơn lại mọi thứ bên trong nó theo thứ tự z thích hợp. Có thể có một cấp gọi điện thoại gián tiếp / công văn động ở đây để kích hoạt các sự kiện sơn trong mỗi tiện ích nằm trong một ô cần được sơn lại, nhưng đó chỉ là một lớp của các cuộc gọi gián tiếp. Biến điều kiện sử dụng mẫu quan sát viên để cảnh báo PaintSystemrằng nó có công việc phải làm, nhưng nó không chỉ định gì hơn thế vàPaintSystemđược dành cho một đồng phục, nhiệm vụ rất đồng nhất tại thời điểm đó. Khi chúng tôi gỡ lỗi và truy tìm PaintSystem'smã, chúng tôi biết rằng sẽ không có gì khác xảy ra ngoài việc vẽ.

Vì vậy, chủ yếu là về việc đưa hệ thống xuống nơi bạn có những điều này thực hiện các vòng lặp đồng nhất đối với dữ liệu áp dụng một trách nhiệm rất đơn lẻ đối với nó thay vì các vòng lặp không đồng nhất đối với các loại dữ liệu khác nhau thực hiện nhiều trách nhiệm như chúng ta có thể xử lý hàng đợi sự kiện.

Chúng tôi đang nhắm đến loại điều này:

when there's work to do:
   for each thing:
       apply a very specific and uniform operation to the thing

Như trái ngược với:

when one specific event happens:
    do something with relevant thing
in relevant thing's event:
    do some more things
in thing1's triggered by thing's event:
    do some more things
in thing2's event triggerd by thing's event:
    do some more things:
in thing3's event triggered by thing2's event:
    do some more things
in thing4's event triggered by thing1's event:
    cause a side effect which shouldn't be happening
    in this order or from this thread.

Và kể từ đó trở đi. Và nó không phải là một chủ đề cho mỗi nhiệm vụ. Một luồng có thể áp dụng logic bố cục (thay đổi kích thước / định vị lại) cho các điều khiển GUI và sơn lại chúng, nhưng nó có thể không xử lý các lần nhấp chuột hoặc bàn phím. Vì vậy, bạn có thể xem điều này như chỉ cải thiện tính đồng nhất của hàng đợi sự kiện. Nhưng chúng ta không phải sử dụng hàng đợi sự kiện và xen kẽ các chức năng thay đổi kích thước và vẽ. Chúng ta có thể làm như:

in thread dedicated to layout and painting:
    when there's work to do:
         for each widget that needs resizing/reposition:
              resize/reposition thing to target size/position
              mark appropriate grid cells as needing repainting
         for each grid cell that needs repainting:
              repaint cell
         go back to sleep

Vì vậy, cách tiếp cận trên chỉ sử dụng một biến điều kiện để thông báo cho luồng khi có việc cần làm, nhưng nó không xen kẽ các loại sự kiện khác nhau (thay đổi kích thước trong một vòng lặp, vẽ trong một vòng lặp khác, không phải là hỗn hợp của cả hai) và nó không ' không bận tâm để truyền đạt những gì công việc chính xác cần phải được thực hiện (chủ đề "phát hiện ra" khi thức dậy bằng cách nhìn vào trạng thái toàn hệ thống của ECS). Mỗi vòng lặp mà nó thực hiện sau đó rất đồng nhất về bản chất, giúp dễ dàng suy luận về thứ tự mà mọi thứ xảy ra.

Tôi không chắc nên gọi kiểu tiếp cận này là gì. Tôi chưa thấy các công cụ GUI khác làm điều này và đó là cách tiếp cận kỳ lạ của riêng tôi đối với tôi. Nhưng trước đây khi tôi cố gắng triển khai các khung GUI đa luồng bằng cách sử dụng các trình quan sát hoặc hàng đợi sự kiện, tôi đã gặp khó khăn rất lớn trong việc gỡ lỗi và cũng gặp phải một số điều kiện cuộc đua tối nghĩa và những bế tắc mà tôi không đủ thông minh để khắc phục theo cách khiến tôi cảm thấy tự tin về giải pháp (một số người có thể làm điều này nhưng tôi không đủ thông minh). Thiết kế lặp đầu tiên của tôi chỉ gọi một vị trí trực tiếp thông qua tín hiệu và một số vị trí sau đó sẽ sinh ra các luồng khác để thực hiện công việc không đồng bộ, và đó là lý do khó nhất để giải quyết và tôi đã vấp ngã trong điều kiện cuộc đua và bế tắc. Lặp lại thứ hai đã sử dụng một hàng đợi sự kiện và đó là lý do dễ dàng hơn một chút về, nhưng không đủ dễ dàng để bộ não của tôi làm điều đó mà không phải chạy vào bế tắc tối nghĩa và điều kiện chủng tộc. Lặp lại thứ ba và cuối cùng đã sử dụng cách tiếp cận được mô tả ở trên và cuối cùng cho phép tôi tạo ra một khung GUI đa luồng mà ngay cả một người đơn giản ngu ngốc như tôi cũng có thể thực hiện chính xác.

Sau đó, kiểu thiết kế GUI đa luồng cuối cùng này cho phép tôi đưa ra một thứ khác dễ hiểu hơn nhiều và tránh những loại lỗi mà tôi có xu hướng mắc phải, và một trong những lý do khiến tôi thấy nó dễ dàng hơn rất nhiều ít nhất là do các vòng lặp đồng nhất này và cách chúng giống với luồng điều khiển tương tự như khi tôi bỏ phiếu trong những ngày DOS (mặc dù nó không thực sự bỏ phiếu và chỉ thực hiện công việc khi hoàn thành công việc). Ý tưởng là di chuyển càng xa mô hình xử lý sự kiện càng tốt, trong đó ngụ ý các vòng lặp không đồng nhất, tác dụng phụ không đồng nhất, các luồng điều khiển không đồng nhất và hoạt động nhiều hơn đối với các vòng lặp đồng nhất hoạt động thống nhất trên dữ liệu đồng nhất và cách ly và thống nhất các tác dụng phụ theo những cách giúp dễ dàng hơn chỉ tập trung vào "cái gì"


1
"Giống như sử dụng các biến điều kiện để thông báo cho các chủ đề để đánh thức" Âm thanh giống như sự sắp xếp dựa trên sự kiện / người quan sát, không bỏ phiếu.
Josh Caswell

Tôi thấy sự khác biệt rất tinh tế nhưng thông báo chỉ ở dạng "Có việc phải làm" để đánh thức các chủ đề. Ví dụ, một mẫu quan sát viên có thể, khi thay đổi kích thước điều khiển cha, tầng thay đổi kích thước các cuộc gọi xuống hệ thống phân cấp bằng cách sử dụng công văn động. Mọi thứ sẽ có chức năng thay đổi kích thước sự kiện của họ được gọi gián tiếp ngay lập tức. Sau đó, họ có thể sơn lại ngay lập tức. Sau đó, nếu chúng ta sử dụng hàng đợi sự kiện, thay đổi kích thước điều khiển cha mẹ có thể đẩy thay đổi kích thước sự kiện xuống cấu trúc phân cấp, tại đó, chức năng thay đổi kích thước cho mỗi điều khiển có thể được gọi theo kiểu trì hoãn, tại đó ...

... điểm sau đó họ có thể đẩy các sự kiện sơn lại, tương tự, được gọi theo kiểu hoãn lại sau khi mọi thứ kết thúc thay đổi kích thước, và tất cả từ một luồng xử lý sự kiện trung tâm. Và tôi thấy rằng việc tập trung hóa có lợi ít nhất là khi gỡ lỗi và có thể dễ dàng suy luận về nơi diễn ra quá trình xử lý (bao gồm cả luồng nào) ... Sau đó, những gì tôi đang xem là gần nhất với việc bỏ phiếu không phải là những giải pháp này ...

Chẳng hạn, nó sẽ có một LayoutSystemcái bình thường đang ngủ, nhưng khi người dùng thay đổi kích thước điều khiển, nó sẽ sử dụng một biến điều kiện để đánh thức LayoutSystem. Sau đó, LayoutSystemthay đổi kích thước tất cả các điều khiển cần thiết và trở lại giấc ngủ. Trong quá trình này, các khu vực hình chữ nhật mà các vật dụng cư trú được đánh dấu là cần cập nhật, tại thời điểm đó PaintSystemthức dậy và đi qua các khu vực hình chữ nhật đó, sơn lại những khu vực cần được vẽ lại trong một vòng tuần tự phẳng.

Vì vậy, biến điều kiện tự nó tuân theo một mẫu quan sát để thông báo cho các chủ đề thức dậy, nhưng chúng tôi không truyền bất kỳ thông tin nào nhiều hơn, "có việc phải làm". Và mỗi hệ thống thức dậy được dành riêng để xử lý mọi thứ trong một vòng lặp rất đơn giản áp dụng một nhiệm vụ rất đồng nhất, trái ngược với một hàng đợi sự kiện có các nhiệm vụ không đồng nhất (nó có thể chứa một hỗn hợp các sự kiện chiết trung để xử lý).

-4

Tôi sẽ cung cấp cho bạn một cái nhìn tổng quan hơn về cách suy nghĩ khái niệm về người quan sát. Hãy suy nghĩ về một kịch bản như đăng ký một kênh youtube. Có số lượng người dùng đăng ký kênh và một khi sẽ có bất kỳ cập nhật nào trên kênh bao gồm nhiều video mà người đăng ký nhận được thông báo rằng có sự thay đổi trong kênh cụ thể này. Vì vậy, chúng tôi đã kết luận rằng nếu kênh là ĐỐI TƯỢNG có khả năng đăng ký, hủy đăng ký và thông báo cho tất cả các OBSERVER đã đăng ký trong kênh.


2
điều này thậm chí không cố gắng giải quyết câu hỏi được hỏi, khi nào việc bỏ phiếu cho các sự kiện sẽ tốt hơn là sử dụng mẫu quan sát viên. Xem cách trả lời
gnat
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.