Làm thế nào để Windows biết nếu một chương trình không đáp ứng? Nó liên tục bỏ phiếu tất cả các ứng dụng đang chạy?
Làm thế nào để Windows biết nếu một chương trình không đáp ứng? Nó liên tục bỏ phiếu tất cả các ứng dụng đang chạy?
Câu trả lời:
Một ứng dụng nhận các sự kiện từ hàng đợi được cung cấp bởi Windows.
Nếu ứng dụng không thăm dò sự kiện trong một thời gian (5 giây), ví dụ như khi thực hiện một phép tính dài, thì Windows giả định rằng ứng dụng bị treo và cảnh báo cho người dùng.
Để tránh điều đó, các ứng dụng nên đẩy các tính toán đắt tiền đến các luồng công nhân hoặc phân tách xử lý và đảm bảo hàng đợi được bỏ phiếu thường xuyên.
GetMessage
(hoặc tương tự) và DispatchMessage
.
IsHungAppWindow
ghi chú chính xác rằng một chương trình trong giai đoạn khởi động không phải gọi GetMessage
.
GetMessage
? Tính năng này cho phép các ứng dụng dòng lệnh đơn giản hoạt động mà không bị coi là treo vì chúng không cần thăm dò hàng đợi.
Không có mã nguồn cho Windows, chúng ta không thể chắc chắn nó đang làm gì bên trong.
Có một chức năng SDK Windows IsHungAppWindow
có thể được sử dụng.
Một ứng dụng được coi là không phản hồi nếu không chờ đầu vào, không xử lý khởi động và chưa được gọi là PeekMessage trong khoảng thời gian chờ nội bộ là 5 giây.
Nguồn IsHungAppWindow chức năng
Nếu một cửa sổ cấp cao nhất dừng trả lời tin nhắn trong hơn vài giây, hệ thống sẽ coi cửa sổ đó không phản hồi. Trong trường hợp này, hệ thống ẩn cửa sổ và thay thế nó bằng một cửa sổ ma có cùng thứ tự Z, vị trí, kích thước và thuộc tính hình ảnh. Điều này cho phép người dùng di chuyển nó, thay đổi kích thước hoặc thậm chí đóng ứng dụng. Tuy nhiên, đây là những hành động duy nhất có sẵn vì ứng dụng thực sự không đáp ứng.
Nguồn Giới thiệu về Tin nhắn và Hàng đợi Tin nhắn
Không. Ứng dụng không được thăm dò nhưng thời gian xử lý.
Windows có một hệ thống lập lịch cung cấp thời gian xử lý cho các luồng ứng dụng.
Thuật toán lập lịch rất phức tạp và được mô tả đầy đủ trong Windows Internals, Phần 1 (Phiên bản thứ 6) (Tham khảo dành cho nhà phát triển) .
PeekMessage
. Vì vậy, khi Windows gửi tin nhắn đến ứng dụng và không nhận được tín hiệu trong vòng năm giây, nó sẽ đánh dấu ứng dụng là không phản hồi. Và trên thực tế, trên Windows gần đây, cửa sổ chỉ được đánh dấu là "không phản hồi" nếu không đáp ứng kịp thời với đầu vào của người dùng - cho đến khi tôi cố gắng bấm hoặc bấm phím hoặc một cái gì đó, ứng dụng có thể dễ dàng bị "treo" phút mà không "xuất hiện" không đáp ứng.
Trên thực tế, Windows không phải lúc nào cũng biết rằng một ứng dụng không phản hồi. Ứng dụng phải là một ứng dụng tương tác với một cửa sổ và cửa sổ phải nhận được thông báo rằng ứng dụng không xử lý được, trước khi Windows kết luận rằng ứng dụng không phản hồi.
Chẳng hạn, Windows không có cách nào để biết liệu một ứng dụng xử lý số không có giao diện người dùng được chạy từ dòng lệnh đang làm việc của nó hay có thể bị kẹt trong một vòng lặp vô hạn.
Các ứng dụng đồ họa tương tác trong Windows nhận các sự kiện bằng cách liên tục bỏ phiếu hàng đợi tin nhắn. Windows điền vào hàng đợi tin nhắn này với các sự kiện bàn phím, chuột, hẹn giờ, v.v. Nếu một ứng dụng không thăm dò hàng đợi tin nhắn trong một thời gian (5 giây là thời gian chờ được đề cập trong tài liệu chức năng IsHungAppWindow ()), Windows sẽ xem xét ứng dụng "treo", ứng dụng có thể biểu thị bằng cách thay đổi tiêu đề cửa sổ (thêm văn bản " (Không phản hồi) "hoặc văn bản tương đương trong các phiên bản được bản địa hóa) và tô màu nội dung cửa sổ nếu người dùng cố gắng tương tác với cửa sổ.
Các ứng dụng có thể treo theo những cách mà Windows không nhận ra. Chẳng hạn, một ứng dụng có thể tiếp tục bỏ phiếu cho các tin nhắn trong hàng đợi tin nhắn của nó mà không hành động đúng với chúng, vì vậy đối với tất cả các ý định và mục đích thực tế, nó sẽ xuất hiện "treo" mà Windows không nhận ra rằng nó không phản hồi.
Windows là một hệ điều hành, nó giám sát tất cả các chương trình đang chạy.
Windows giao tiếp với các ứng dụng dựa trên cửa sổ bằng các sự kiện. Mỗi chương trình có một luồng liên tục lắng nghe các sự kiện đến và xử lý chúng. Ví dụ: khi bạn nhấp vào nút hoặc biểu tượng vùng thông báo, Windows sẽ tạo sự kiện và đưa nó vào quy trình thích hợp. Quá trình sau đó có thể quyết định làm thế nào để xử lý nó.
Tất cả các tương tác với các chương trình đều dựa trên sự kiện trong Windows, vì vậy khi chương trình không xử lý các sự kiện đến quá lâu, điều đó có nghĩa là nó không phản hồi. Như @DavidPostill đã tìm thấy và ghi chú trong câu trả lời của mình , thời gian chờ là 5 giây. PeekMessage
là chức năng nhận được một sự kiện từ hàng đợi sự kiện.
Câu trả lời cho câu hỏi của bạn là có / KHÔNG.
Mặc dù HĐH Windows có thể và thực hiện các ứng dụng thăm dò các sự kiện trong Hàng đợi Nhắn tin của Windows, các chương trình hoàn toàn không có nghĩa vụ liên kết với WinAPI hoặc xử lý / trả lời Hàng đợi Windows. Ngay cả việc trả lời tin nhắn trong Hàng đợi cũng không cho Windows biết chương trình có "bị khóa" hay không. Đó là một chỉ số, nhưng đó là tất cả. Câu trả lời thực sự phức tạp hơn một chút.
Câu trả lời thực sự
Mọi người đang phòng ngừa xung quanh câu trả lời thực tế ở đây. Xác định xem một chương trình "không phản hồi" có phải là một biến thể của " vấn đề tạm dừng " hay không, điều này là không thể giải quyết được trong khoa học máy tính. Giải thích ngắn gọn là bộ xử lý không thể hoạt động như một bên thứ ba tự quan sát để xác định liệu chương trình con có bị kẹt trong một vòng lặp vô hạn hay không, không làm gì so với việc tăng bộ đếm sẽ chấm dứt ở một số số cố định, bình thường. Cả hai điều này có thể được coi là các vòng khép kín. Một dừng lại, khác sẽ không bao giờ chấm dứt. Ngay cả bạn, với tư cách là một người, không biết liệu một chương trình có thực sự đáp ứng hay không, đặc biệt là nếu nó nằm trong một vòng khép kín - bạn chỉ biết nếu nghĩ rằng nó nên (phản hồi).
Từ quan điểm của Windows, cả hai vòng lặp này đều "không đáp ứng" . Đó là lý do tại sao các cửa sổ cho bạn lựa chọn chờ đợi hoặc chấm dứt, bởi vì nó không thể biết được.
Vì vậy, hệ quả là "tại sao các cửa sổ biết rằng một quá trình đang đáp ứng?" Câu trả lời là khá thông minh. Khi một tiến trình được biên dịch trong HĐH đa luồng & đa tiến trình, đôi khi ngay cả trong các vòng lặp được đóng chặt, trình biên dịch có thể thêm vào một lệnhield () , cung cấp một thông báo thuận tiện cho bộ xử lý để nó có thể chuyển sang các tiến trình đang chạy khác . Nó "từ bỏ" bộ xử lý và "chuyển đổi ngữ cảnh" (như được gọi) xảy ra cho phép HĐH (bao gồm Windows) trả lời các sự kiện khác trong ngăn xếp, một số trong đó bao gồm theo dõi quá trình đã phản hồi.
** Điều này không có nghĩa là một quá trình đáp ứng sẽ chấm dứt . ** Một quy trình bên trong một vòng lặp vô hạn có thể mang lại bộ xử lý, cho phép Windows xử lý các sự kiện khác.
Trong một số chương trình windows, chương trình sẽ xử lý các tín hiệu HĐH Windows, có thể cho HĐH biết nó đang "phản hồi", nhưng không có chương trình nào có nghĩa vụ phải làm như vậy. Bạn có thể viết các CPU khá đơn giản, các chương trình không kết thúc ngay cả bên trong các ngôn ngữ cấp cao hơn trên Windows như perl, php, python và Windows có thể không phát hiện ra rằng nó không kết thúc và không phản hồi. Tại thời điểm đó, Windows phụ thuộc vào phương pháp phỏng đoán - tải CPU, bộ nhớ, có bao nhiêu ngắt bộ xử lý được xử lý trong khi chương trình đang chạy để "đoán". Một lần nữa, tại thời điểm đó, Windows phải yêu cầu bạn chấm dứt, bởi vì nó thực sự không biết có nên hay không.
Xem thêm câu trả lời (đúng) của Viktor. Bỏ qua các ý kiến về việc "không trả lời" không giống như một vòng lặp vô hạn. Có tất cả các loại tin nhắn, ngắt, vòng lặp mà một ứng dụng có thể hoặc không thể xử lý mà không thông báo cho hàng đợi tin nhắn Windows. Xử lý hàng đợi tin nhắn chỉ là một trong nhiều loại sự kiện mà HĐH tiếp tục truy cập để cố gắng đoán xem liệu một quy trình có bị treo hay không.