2011-12-18 31 views
14

tôi làm hiểu những gì một APC , làm thế nào nó hoạt động, và làm thế nào của Windows sử dụng nó, nhưng tôi không hiểu khi tôi (như là một lập trình viên) nên sử dụng QueueUserAPC thay vì, nói rằng, một chất xơ, hoặc thread thread thread.Khi nào sử dụng QueueUserAPC()?

Khi nào tôi nên chọn sử dụng QueueUserAPC và tại sao?

+1

Đây là mức tương đương ở mức thấp của vòng lặp tin nhắn Windows. Nó cho phép bạn chèn mã vào một luồng một cách an toàn. Chủ đề báo hiệu rằng nó đã sẵn sàng để đối phó với sự ủy thác lại bằng cách thực hiện một sự chờ đợi có thể cảnh báo. Giống như gọi GetMessage(). –

+0

@ HansPassant: Hmmm ... Tôi đoán vậy, nhưng tôi không thấy nó giống như GetMessage(). GetMessage chỉ đơn giản là lấy một tin nhắn, trong khi QueueUserAPC * gọi * phương thức - vì vậy nó có thể gây ra một tràn ngăn xếp, phải không? Họ dường như khác nhau ... – Mehrdad

+0

Chỉ muốn nhớ mọi người rằng "GetMessage" KHÔNG phải là một sự chờ đợi có thể cảnh báo được.Và @Mehrdad, không có QueueUserAPC sẽ không gọi phương thức cho đến khi thread sẵn sàng xử lý chúng luôn luôn rõ ràng trong mã nguồn – Lothar

Trả lời

15

QueueUserAPC là một công cụ gọn gàng thường có thể là lối tắt cho một số tác vụ được xử lý bằng các đối tượng đồng bộ hóa. Nó cho phép bạn nói một chuỗi cụ thể để làm điều gì đó bất cứ khi nào thuận tiện cho luồng đó (tức là khi nó kết thúc công việc hiện tại của nó và bắt đầu chờ đợi một thứ gì đó).

Giả sử bạn có chuỗi chính và chuỗi công nhân. Chuỗi công nhân mở một ổ cắm đến một máy chủ tệp và bắt đầu tải xuống tệp 10GB bằng cách gọi recv() trong một vòng lặp. Các chủ đề chính muốn có thread công nhân làm cái gì khác trong thời gian chết của nó trong khi nó đang chờ đợi các gói tin net; nó có thể xếp hàng một chức năng để chạy trên công nhân trong khi nó sẽ được chờ đợi và không làm gì cả.

Bạn phải cẩn thận với APC, vì như trong kịch bản tôi đã đề cập bạn sẽ không muốn thực hiện cuộc gọi chặn WinSock khác (điều này sẽ dẫn đến hành vi không xác định). Bạn thực sự phải được theo dõi để tìm thấy bất kỳ sử dụng tốt của chức năng này bởi vì bạn có thể làm điều tương tự theo những cách khác. Ví dụ, bằng cách để chủ đề khác kiểm tra một sự kiện mỗi khi nó sắp đi ngủ, thay vì cho nó một hàm để chạy trong khi nó đang chờ. Rõ ràng APC sẽ đơn giản hơn trong kịch bản này.

Cũng giống như khi bạn có nhân viên gọi điện ngồi và chờ cuộc gọi điện thoại, và bạn cho người đó ít việc phải làm trong thời gian ngừng hoạt động của họ. "Đây, giải quyết khối lập phương của Rubik này trong khi cậu đang đợi." Mặc dù, khi một cuộc gọi điện thoại đến, người đó sẽ không đặt khối lập phương của Rubik để trả lời điện thoại (APC phải quay trở lại trước khi luồng có thể quay lại chờ đợi).

QueueUserAPC cũng hữu ích nếu có một chuỗi đơn (luồng A) chịu trách nhiệm về một số cấu trúc dữ liệu và bạn muốn thực hiện một số thao tác trên cấu trúc dữ liệu từ chuỗi khác (Chủ đề B), nhưng bạn không ' t muốn có sự đồng bộ trên không/phức tạp của việc cố gắng chia sẻ dữ liệu đó giữa hai luồng. Khi Thread B xếp hàng hoạt động để chạy trên Thread A, chỉ duy trì cấu trúc đó, bạn đang thực hiện bất kỳ chức năng tùy ý nào mà bạn muốn trên dữ liệu đó mà không phải lo lắng về việc đồng bộ hóa.

Nó chỉ là một công cụ khác như một nhóm luồng. Tuy nhiên với một hồ bơi thread bạn không thể gửi một nhiệm vụ cho một chủ đề cụ thể. Bạn không có quyền kiểm soát nơi công việc được thực hiện. Khi bạn xếp hàng một tác vụ có thể sẽ tạo ra một chuỗi hoàn toàn mới. Bạn có thể xếp hàng hai nhiệm vụ và chúng được thực hiện đồng thời trên hai luồng khác nhau. Với QueueUserAPC, bạn có thể được đảm bảo rằng các tác vụ sẽ được thực hiện theo thứ tự và trên chuỗi bạn chỉ định.

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