2010-12-27 21 views
17

Tôi có một số ManualResetEvent. Tại một thời điểm, tôi chờ đợi sự kiện đó bằng cách sử dụng WaitOne. Trước sự ngạc nhiên của tôi, tôi đã nhận được sự kiện OnPaint khi đang ở trong WaitOne. Điều này xảy ra khá thường xuyên.Điều này có thể xảy ra như thế nào: OnPaint được xử lý trong khi ở WaitOne

Các vết đống trông như thế này:

alt text

Tôi hiểu rằng một WaitOne sẽ chặn các chủ đề hiện tại và sẽ không cho phép bất kỳ mã khác được thực hiện cho đến khi sự kiện cháy.

Ai đó có thể giải thích điều gì xảy ra ở đây?

Trả lời

20

Đây là theo thiết kế. CLR tôn trọng hợp đồng của một căn hộ đơn luồng (STA). Chủ đề chính của ứng dụng GUI là STA như được yêu cầu trong lập trình Windows, thuộc tính [STAThread] trên phương thức Main() đảm bảo điều đó.

Quy tắc cứng cho chuỗi STA là nó phải bơm vòng lặp thông báo (như Application.Run) và không bao giờ có thể chặn. Việc chặn một chuỗi STA có nhiều khả năng gây ra bế tắc khi chủ đề nền sử dụng bất kỳ đối tượng ren căn hộ nào của COM. Có rất nhiều người trong số họ, clipboard và WebBrowser là những cái phổ biến mà bạn sẽ gặp phải trong một chương trình .NET. Nhiều cái ít hiển thị hơn, có sẵn dưới dạng các lớp trình bao bọc .NET.

CLR đảm bảo chặn không thể gây tắc nghẽn bằng cách bơm vòng lặp thông báo khi bạn sử dụng báo cáo khóa hoặc gọi phương thức Chờ của các lớp đồng bộ hóa. Hoặc Thread.Join(). Vòng lặp tin nhắn đó gửi đi thông điệp WM_PAINT, gây ra sự kiện Paint để chạy.

Bạn cần phải cơ cấu lại chương trình của mình để đảm bảo điều này không gây ra sự cố. Khá quan trọng để tập trung vào việc không chặn chủ đề chính chút nào. Nó là rất hiếm khi cần thiết khi bạn có, nói, lớp BackgroundWorker hoặc Control.BeginInvoke() theo ý của bạn. Vì một lý do kỳ lạ nào đó, lớp Mutex không làm loại bơm này, đó có thể là một cách khác. Mặc dù bế tắc đang rình rập quanh góc nếu bạn làm vậy.

+0

Câu trả lời của bạn luôn là thông tin chi tiết, đã học được điều gì đó mới mẻ. – BrokenGlass

+0

Lý do tôi chờ đợi là vì tôi đang đợi lưu lượng truy cập mạng hoàn tất. Máy chủ cung cấp dữ liệu tôi cần để xây dựng giao diện người dùng. Cụ thể, tôi đang lười tải chế độ xem danh sách. Khi một hàng đi vào xem mà tôi không có dữ liệu, tôi cần phải lấy dữ liệu đó để có thể phản ứng với sơn. Điều này là do thiết kế. Tôi sẽ xem liệu lớp 'Mutex' có giúp ích gì không. Nếu bạn có đề xuất khác, họ chắc chắn được chào đón. –

+0

Chỉ cần làm điều này theo cách khác. Sự xuất hiện của dữ liệu có thể gây ra sự kiện sơn. Control.BeginInvoke và Invalidate(). Điều này sẽ dễ dàng hơn rất nhiều trong C# 5 với asych/await. Sử dụng một máy nhà nước nếu cần thiết cho đến khi đó. –

3

Tôi cũng đã thấy hành vi này đối với tuyên bố lock(). Rõ ràng lớp .net framework Các lớp Thread bắt đầu một vòng lặp tin nhắn khi chờ một khóa trên chuỗi giao diện người dùng. Điều này chỉ giải thích những gì đang xảy ra. Lý do có thể là để ngăn chặn deadlocks khi làm việc với các đối tượng STA COM cũ. Tôi không biết cách ngăn chặn điều này.

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