2015-08-04 13 views
6

Các câu hỏi liên quan chặt chẽ đã được hỏi trước:Tại sao phải/nên UI framework là đơn luồng?

Nhưng câu trả lời cho những câu hỏi đó vẫn để lại cho tôi rõ ràng trên một số điểm.

  • Người hỏi các câu hỏi đầu tiên được hỏi liệu đa luồng sẽ giúp hiệu suất, và người trả lời chủ yếu là nói rằng nó sẽ không, bởi vì nó là rất không chắc rằng GUI sẽ là nút cổ chai trong một ứng dụng 2D trên hiện đại phần cứng. Nhưng điều này dường như với tôi một chiến thuật tranh luận lén lút. Chắc chắn, nếu bạn đã cấu trúc cẩn thận ứng dụng của mình để không làm gì ngoài các cuộc gọi giao diện người dùng trên chuỗi giao diện người dùng, bạn sẽ không bị nút cổ chai. Nhưng điều đó có thể mất nhiều công sức và làm cho mã của bạn phức tạp hơn và nếu bạn có lõi nhanh hơn hoặc có thể thực hiện cuộc gọi giao diện người dùng từ nhiều luồng, có thể nó sẽ không đáng làm.

  • Thiết kế kiến ​​trúc thường được ủng hộ là có các thành phần xem không có gọi lại và không cần khóa bất kỳ thứ gì ngoại trừ có thể là hậu duệ của chúng. Theo một kiến ​​trúc như vậy, bạn không thể để bất kỳ luồng nào gọi các phương thức trên các đối tượng xem, sử dụng các khóa cho mỗi đối tượng, mà không sợ bế tắc?

  • Tôi ít tự tin hơn về tình hình với điều khiển giao diện người dùng, nhưng thời gian gọi lại của họ chỉ được hệ thống gọi, tại sao họ phải gây ra bất kỳ sự cố bế tắc nào đặc biệt? Sau khi tất cả, nếu callbacks cần phải làm bất cứ điều gì tốn thời gian, họ sẽ đại biểu cho chủ đề khác, và sau đó chúng tôi trở lại ngay trong trường hợp nhiều chủ đề.

  • Bạn sẽ nhận được bao nhiêu lợi ích của giao diện người dùng đa luồng nếu bạn chỉ có thể chặn trên chuỗi giao diện người dùng? Bởi vì các abstractions đang nổi lên khác nhau trên async có hiệu lực cho phép bạn làm điều đó.

  • Hầu như tất cả các cuộc thảo luận mà tôi đã thấy đều cho rằng đồng thời sẽ được xử lý bằng cách sử dụng khóa thủ công, nhưng có một sự đồng thuận rộng rãi rằng việc khóa thủ công là cách xấu để quản lý đồng thời trong hầu hết các ngữ cảnh. Thảo luận thay đổi như thế nào khi chúng ta xem xét các nguyên tắc đồng thời mà các chuyên gia đang khuyên chúng ta sử dụng nhiều hơn, chẳng hạn như bộ nhớ giao dịch phần mềm, hoặc tránh bộ nhớ dùng chung để chuyển thông điệp (có thể với đồng bộ hóa).

Trả lời

9

TL; DR

Đó là một cách đơn giản để buộc trình tự xảy ra trong một hoạt động mà sẽ cuối cùng được theo thứ tự nào (thời gian màn hình bốc X mỗi giây, theo thứ tự) .

Thảo luận

Xử lý nguồn lực lâu nay có một bản sắc duy nhất trong một hệ thống thường được thực hiện bởi đại diện chúng với một chủ đề duy nhất, quá trình, "đối tượng" hay bất cứ điều gì khác đại diện cho một đơn vị nguyên tử đối với với đồng thời trong một ngôn ngữ nhất định. Quay trở lại, không có dấu hiệu, cẩu thả-hạt nhân, không timeshared, One True Thread ngày này được quản lý bằng tay bằng cách bỏ phiếu/đi xe đạp hoặc viết hệ thống lập kế hoạch của riêng bạn. Trong hệ thống như vậy, bạn vẫn có một bản đồ 1 :: 1 giữa hàm/đối tượng/thingy và các tài nguyên số ít (hoặc bạn phát điên trước lớp 8).

Đây là phương pháp tương tự được sử dụng để xử lý các ổ cắm mạng hoặc bất kỳ tài nguyên sống lâu nào khác. Bản thân GUI là một trong nhiều tài nguyên như vậy, một chương trình điển hình quản lý và các tài nguyên thường tồn tại lâu dài là những nơi mà thứ tự các sự kiện quan trọng.

Ví dụ: trong chương trình trò chuyện, bạn thường không viết một chuỗi. Bạn sẽ có một chủ đề GUI, một chuỗi mạng và có thể một số luồng khác đề cập đến tài nguyên ghi nhật ký hoặc bất kỳ thứ gì. Nó không phải là không phổ biến cho một hệ thống điển hình để được nhanh như vậy mà nó dễ dàng hơn để chỉ cần đặt đăng nhập và đầu vào vào cùng một thread mà làm cho giao diện đồ họa, nhưng điều này không phải luôn luôn như vậy. Tuy nhiên, trong mọi trường hợp, mỗi loại tài nguyên dễ dàng được lý luận nhất bằng cách cấp cho chúng một luồng đơn, và đó có nghĩa là một luồng cho mạng, một luồng cho GUI, và nhiều chuỗi khác cần thiết cho các hoạt động lâu dài hoặc các nguồn lực được quản lý mà không cần chặn những người khác.

Để làm cho cuộc sống trở nên dễ dàng hơn, hãy phổ biến để không phải chia sẻ dữ liệu trực tiếp giữa các chủ đề này càng nhiều càng tốt. Hàng đợi dễ dàng hơn nhiều để lý luận hơn là khóa tài nguyên và có thể đảm bảo trình tự. Hầu hết các thư viện GUI xếp hàng các sự kiện cần xử lý (để chúng có thể được đánh giá theo thứ tự) hoặc cam kết thay đổi dữ liệu theo yêu cầu của các sự kiện ngay lập tức, nhưng nhận được khóa trên trạng thái GUI trước mỗi lần lặp của vòng lặp. Nó không quan trọng những gì đã xảy ra trước đây, điều duy nhất quan trọng khi vẽ màn hình là trạng thái của thế giới ngay sau đó. Điều này hơi khác so với trường hợp mạng điển hình, nơi tất cả dữ liệu cần được gửi theo thứ tự và quên đi một số dữ liệu không phải là một tùy chọn.

Vì vậy, khung công tác GUI không phải là đa luồng, mỗi lần, đó là vòng lặp GUI cần phải là một chuỗi duy nhất để quản lý một cách an toàn tài nguyên được giữ nguyên duy nhất đó. Các ví dụ lập trình, thường là không quan trọng, thường là một luồng đơn với tất cả logic chương trình đang chạy trong cùng một tiến trình/luồng như vòng lặp GUI, nhưng điều này không điển hình trong các chương trình phức tạp hơn.

Tóm lại

Bởi vì lịch trình là khó khăn, quản lý dữ liệu chia sẻ thậm chí còn khó khăn hơn, và một nguồn duy nhất chỉ có thể được truy cập serially dù sao, một chủ đề duy nhất sử dụng để đại diện cho mỗi tài nguyên lâu nay và mỗi dài thủ tục -running là một cách điển hình để cấu trúc mã. GUIs chỉ là một trong những tài nguyên trong số một số chương trình điển hình sẽ quản lý. Vì vậy, "các chương trình GUI" không có nghĩa là đơn luồng, nhưng các thư viện GUI thường là.

Trong các chương trình tầm thường không có hình phạt thực hiện để đặt logic chương trình khác trong luồng GUI, nhưng cách tiếp cận này bị phân tách khi tải trọng đáng kể hoặc quản lý tài nguyên yêu cầu chặn hoặc bỏ phiếu nhiều. xem hàng đợi sự kiện, trừu tượng thông báo khe cắm tín hiệu hoặc các cách tiếp cận đa luồng/xử lý khác được đề cập trong các góc bụi của hầu hết thư viện GUI (và ở đây tôi bao gồm thư viện trò chơi - trong khi lib trò chơi thường mong muốn bạn muốn xây dựng các tiện ích của riêng bạn xung quanh khái niệm giao diện người dùng của riêng bạn, các nguyên tắc cơ bản rất giống nhau, chỉ một chút cấp thấp hơn).

[Ngoài ra, gần đây tôi đã thực hiện rất nhiều Qt/C++ và Wx/Erlang. The Qt docs do a good job of explaining approaches to multi-threading, vai trò của vòng lặp GUI và nơi tiếp cận tín hiệu/khe của Qt phù hợp với sự trừu tượng (vì vậy bạn không phải suy nghĩ về đồng thời/khóa/sắp xếp/lập kế hoạch/v.v ...). Erlang vốn dĩ đồng thời, nhưng wx itself is typically started as a single OS process that manages a GUI update loop và Erlang gửi các sự kiện cập nhật lên dưới dạng tin nhắn, và các sự kiện GUI được gửi đến bên Erlang dưới dạng tin nhắn - cho phép mã hóa đồng thời Erlang bình thường, nhưng cung cấp một điểm duy nhất của trình tự sự kiện GUI để wx có thể hãy thực hiện điều chỉnh vòng lặp GUI của nó.]

+0

Cảm ơn, tôi sẽ kiểm tra các liên kết này vào ngày mai.Chỉ cần làm rõ, tôi chắc chắn nhận thức được rằng các chương trình GUI thường được đa luồng nhiều. Đó là một phần lý do tại sao một chuỗi giao diện người dùng duy nhất có thể cảm thấy hạn chế đối với các lập trình viên! Sự hiểu biết của tôi là/đó là lý do chính để hạn chế là để tránh deadlocks (hoặc các lỗi đồng thời khác). Có thể các API async dựa trên thông điệp là cách tiếp cận đúng (nhưng tại sao chúng không phổ biến hơn?). – gmr

+0

@gmr Theo kinh nghiệm của tôi, sự kết hợp giữa thông điệp đi qua và * không chia sẻ trạng thái * đã là một chiến thắng lớn bởi vì nó cho phép một người cô lập lịch trình từ các vấn đề trạng thái. Một lý do thông điệp đi qua không phải là rất phổ biến, tôi nghĩ rằng, từ vựng của OOP conflates "tin nhắn" với "cuộc gọi". Chúng không giống nhau. Một thông báo giữa các tiến trình/đối tượng đồng thời được biểu diễn tốt hơn bằng một hàng đợi đang chạy trong chuỗi riêng của nó. Trong bất kỳ trường hợp nào, nhiều ứng dụng GUI chạy trong một luồng đơn giản chỉ vì không có/không có hình phạt thực thi thấp và dễ dàng hơn nhiều trong việc giải thích các ngôn ngữ kiểu algol. – zxq9

+0

Tôi đã suy nghĩ về điều này ngày hôm nay. Vấn đề với việc truyền thông điệp (không đồng bộ) là bạn không bao giờ biết trạng thái thực tế là gì, vì nó là sự kết hợp của trạng thái được lưu trữ trong các thành phần + trạng thái đang chờ thay đổi trong các máy chủ thông báo của chúng. Nếu bạn không chia sẻ nhà nước bạn đang nhân đôi nó tất nhiên. Tôi thích sự đơn giản khái niệm của mô hình mặc dù. – Robinson

Các vấn đề liên quan