Câu hỏi Định nghĩa của một chuỗi giao diện người dùng là gì? Chỉ có một chuỗi giao diện người dùng trong ứng dụng .NET không?


Chuỗi giao diện người dùng là gì? Chỉ có một chuỗi giao diện người dùng trong ứng dụng .NET không?


12
2018-05-04 19:19


gốc




Các câu trả lời:


(Đơn giản hóa trước)

Một thread UI là một Thread Threading Apartment được sử dụng để tạo các đối tượng giao diện người dùng khác nhau (trong Winforms, điều này có nghĩa là Controls). Theo quy ước và quy tắc, một điều khiển có thể chỉ có được truy cập từ bên trong luồng đã được sử dụng để tạo ra nó; làm theo cách khác có thể và sẽ tạo ra kết quả không mong muốn, từ những điều kỳ quặc về hình ảnh đến đường sụp đổ.

Trừ khi bạn tạo rõ ràng hơn, chỉ có một chuỗi giao diện người dùng trong một ứng dụng Windows Forms. Trong khi bạn có thể tạo một luồng khác và bắt đầu một vòng lặp tin nhắn, có rất ít lý do tại sao bạn muốn làm điều này, và hai luồng giao diện người dùng khác nhau không thể "nói chuyện" với nhau hơn bất kỳ chủ đề nào khác có thể nói chuyện với một chuỗi giao diện người dùng.


12
2018-05-04 19:24



1 để đề cập rằng bạn có thể làm điều này, nhưng đó là hiếm khi cách mọi thứ nên được thực hiện ... - Reed Copsey
Vì vậy, những gì về khi bạn làm mới Thread (). Bắt đầu () bên trong một STAThread?
@Griever: Điều đó bắt đầu một chuỗi mới, nhưng nó hoàn toàn tách biệt khỏi chuỗi giao diện người dùng. Thực hiện một Thread mới bắt đầu ở bất cứ đâu tạo ra một luồng mới, không liên quan. - Reed Copsey
@Reed: Ý của bạn là, nếu tôi tạo một điều khiển bên trong Thread.Start, điều khiển đó sẽ không có bất kỳ bơm thông điệp nào gắn vào nó?
@ Griever: Vâng. Và nếu bạn cố gắng thêm nó vào một hình thức khác, bạn sẽ nhận được lỗi. Đó là, nói chung, một ý tưởng tồi. (Bạn cần phải tạo luồng làm chủ đề STA, sau đó thêm một máy bơm thông báo vào luồng, sau đó tạo biểu mẫu của bạn. Điều đó cho phép bạn bắt đầu một chuỗi giao diện người dùng mới, nhưng nó thực sự là một ý tưởng tồi - có rất ít lý do chính đáng để làm điều đó - vì bạn gần như luôn luôn tốt hơn chỉ cần đẩy "công việc" của bạn vào các chủ đề nền và để lại một chuỗi giao diện người dùng duy nhất tại chỗ) - Reed Copsey


Một chuỗi giao diện người dùng có một số đặc điểm khiến nó trở nên đặc biệt:

  • Windows có hàng đợi tin nhắn được liên kết với chuỗi. Điều này xảy ra ngay khi cửa sổ đầu tiên được tạo trên luồng.
  • Chuỗi chạy một vòng lặp tin nhắn, cho phép Windows gửi tin nhắn đến các cửa sổ. Vòng lặp tin nhắn được tạo ngay khi bạn gọi Application.Run ().
  • COM đã được khởi tạo trên luồng, yêu cầu một căn hộ đơn luồng. Một STA là cần thiết để cho phép nhiều tính năng của Windows hoạt động bình thường, các tính năng không an toàn bằng luồng theo thiết kế. COM đảm bảo rằng các tính năng này luôn được gọi theo cách an toàn theo chủ đề, marshaling cuộc gọi từ một chuỗi công nhân đến chuỗi STA khi cần. Ví dụ về các tính năng này là Kéo + Thả, khay nhớ tạm, hộp thoại vỏ (OpenFileDialog vv), điều khiển ActiveX như WebBrowser, móc cửa sổ do SetWindowsHookEx thiết lập, nhà cung cấp trợ năng như trình đọc màn hình, nhà cung cấp tự động hóa UI. Tất cả các mã bên ngoài, không có chuỗi nào an toàn.
  • Chủ đề không bao giờ chặn trên bất kỳ hoạt động nào, nó vẫn đáp ứng để nó có thể gửi tin nhắn Windows theo yêu cầu để giữ cho giao diện người dùng đáp ứng và yêu cầu marshaling COM chảy. Thực hiện cuộc gọi đến WaitHandle.WaitAny () chẳng hạn bị cấm và tạo ra một ngoại lệ. CLR có hỗ trợ cụ thể cho WaitOne () và lock, bơm một vòng lặp nội bộ để tránh bế tắc.

Chuỗi khởi động của một quy trình hầu như luôn được chọn làm luồng giao diện người dùng, mặc dù đó không phải là yêu cầu khó. Trạng thái STA được chọn bởi thuộc tính [STAThread] trên phương thức Main ().

Bạn có thể tạo một chuỗi giao diện người dùng bằng cách đảm bảo rằng các yêu cầu trên được đáp ứng. Điều đó có thể trông giống như thế này trong một ứng dụng Winforms:

    var ui = new Thread(() => { Application.Run(new Form2()); });
    ui.SetApartmentState(ApartmentState.STA);
    ui.Start();

Điều đó tạo ra một cửa sổ thứ hai, chạy trên chuỗi giao diện người dùng của riêng nó. Một vấn đề điển hình mà bạn có với sự sắp xếp này là bạn đã có hai cửa sổ riêng biệt, chúng không liên kết với nhau. Cửa sổ thứ 2 không thể thuộc sở hữu của 1st, nó có thứ tự Z của riêng nó độc lập với 1st. Khó xử lý bởi người dùng. Các sự kiện SystemEvents.UserPreferenceChanged là đáng chú ý, nó chắc chắn sẽ cháy sự kiện của nó trên thread sai và đó là apt gây ra bế tắc. Rất nhiều điều khiển WinForms đăng ký nó. Ngoại trừ trong những trường hợp hiếm hoi, như màn hình giật gân, điều này không cải thiện giao diện người dùng.


8
2018-05-04 20:35



Tôi thích câu trả lời chi tiết của bạn.


CHỈNH SỬA cho đúng đắn:

Có một chuỗi giao diện người dùng cho mỗi APPLICATION đang hoạt động trong Windows Forms và khái niệm tương tự cho WPF.

tức là: Khi bạn khởi động ứng dụng, có một luồng, nó sẽ trở thành một chuỗi giao diện người dùng khi Application.Run (Form1 mới ()); được gọi là.

Nếu bạn cố gắng làm Application.Run (new Form2 ()); tại thời gian chạy, bạn sẽ nhận được "System.InvalidOperationException: Bắt đầu một vòng lặp tin nhắn thứ hai trên một chủ đề duy nhất không phải là một hoạt động hợp lệ. Sử dụng Form.ShowDialog thay thế."

Nếu bạn thực sự cần hai hình thức riêng biệt để không chia sẻ cùng một chủ đề, bạn sẽ cần phải tạo một chủ đề mới, sau đó gọi Application.Run (new MyForm ()) vv vv Điều này là không phổ biến.


0
2018-05-04 19:23



Đây không phải là sự thật. Các dạng khác nhau, trong Windows Forms, tất cả đều sử dụng tương tự chủ đề. Các máy bơm tin nhắn làm cho họ tất cả đáp ứng. - Reed Copsey
Tôi đã có nó đảo ngược, hộp thoại phương thức đòi hỏi một chủ đề mới, hộp thoại không modeless không yêu cầu một chủ đề mới. Điểm vẫn đứng đó là các luồng bình thường có thể trở thành các luồng ui khi một biểu mẫu mới được khởi chạy từ chúng. - David
Điều này vẫn không đúng sự thật. "Khởi chạy một biểu mẫu" từ một chủ đề mới, mà không cần chăm sóc đặc biệt để bắt đầu một vòng lặp tin nhắn, sẽ gây ra tất cả các loại vấn đề, bao gồm (trong hầu hết các trường hợp) bị lỗi do thiếu STA theo mặc định. - Reed Copsey
Bạn có thể đúng. Có một trường hợp trong quá khứ mà tôi đã cố gắng để hiển thị một biểu mẫu và trong thời gian chạy có một lỗi nói với tôi rằng tôi không thể có hai biểu mẫu mở trên cùng một sợi ui, tôi đang cố gắng theo dõi nó xuống để bình luận ở đây, nhưng tôi thiên đường ' t tìm thấy nó chưa - David
Chỉ cần chỉnh sửa bài viết của tôi, tôi đã nhầm lẫn Application.Run với Form.Show. - David