2011-12-19 23 views
8

Trong một ứng dụng đồ họa, tôi thực hiện các lệnh gỡ rối bằng cách sử dụng đầu vào của giao diện điều khiển. Khi giao diện điều khiển được tạo ra một luồng mới cũng được tạo ra để thu thập các lệnh của người dùng xử lý tất cả các đầu vào đó, ứng dụng đồ họa tiếp tục chạy song song. Tôi sử dụng boost :: thread library.Có thể dừng cin khỏi đầu vào chờ không?

Nó hoạt động tốt cho đến nay, tuy nhiên tôi đã không tìm thấy một giải pháp tốt đẹp để ngăn chặn việc thực hiện chủ đề này. Các chủ đề luôn luôn chờ đợi một người dùng nhập vào:

while(appRunning) 
{ 
    std::cin>>theUserCommand; 
    // ...do stuff 
} 

Sau đó, khi các ứng dụng đồ họa kết thúc, nó sẽ ngừng tất cả các chức năng điều khiển, trong đó tôi bao gồm các chủ đề:

appRunning = false; 
// do some more related clean up 
myListeningThread->join(); 

Như bạn có thể thấy std :: cin sẽ đợi đầu vào của người dùng, sau khi kết nối đã được gọi. Một trong những giải pháp mà tôi đã thử là tạo sự kiện "tổ hợp phím", std :: cin sẽ nhận được bất kỳ giá trị nào bạn gửi với ENTER, chuỗi sẽ kết thúc độc đáo, giải pháp này thật khủng khiếp và tôi không muốn giữ nó . Bên cạnh đó, nó đã làm việc trong một trong các môi trường công cụ được thực hiện, nhưng không thành công khi tôi đã thử sử dụng nó cùng với một API UI. Các bạn có thể hướng dẫn tôi cách tôi có thể sửa lỗi này theo cách chính xác không? Có thể không thực sự nói chắc chắn nếu trong tài liệu C++ có một chức năng để ngăn chặn std :: cin chờ đợi cho người dùng đầu vào, và chỉ và tiếp tục thực hiện chương trình, là nó thậm chí có thể?

EDIT: Tốt Tôi thấy rằng keybd_event là một chút gây hiểu nhầm cho một số môi trường, rõ ràng xác định xử lý đầu vào với WriteConsoleInput hoạt động tốt.

+0

Có một số khả năng, nhưng tất cả đều phụ thuộc vào hệ điều hành. Chương trình này dành cho hệ điều hành nào? – zwol

+0

Win/VStudio9.0, tôi đã sử dụng keybd_event cho giải pháp mà tôi đã đề cập, không có vấn đề gì nếu nó phụ thuộc vào hệ điều hành. bạn đề nghị tôi sửa nó như thế nào? – notNullGothik

+0

BTW, SetConsoleCtrlHandler không thực sự làm việc cho tôi, điều này sẽ kết thúc quá trình ứng dụng bỏ qua tất cả việc dọn dẹp cho ứng dụng kết thúc. – notNullGothik

Trả lời

1

Tôi không phải là một lập trình viên Windows, tôi biết nhiều hơn về Unix. Và tôi hoàn toàn không quen thuộc với boost::thread. Điều đó nói rằng, dựa trên lời khuyên ở dưới cùng của this MSDN page, đây là khuyến nghị của tôi:

  • Tạo một event object trước khi bạn tạo chuỗi giao diện điều khiển.
  • Khi bạn muốn tắt, hãy gọi SetEvent trên đối tượng sự kiện ngay trước khi gọi phương thức ->join của luồng.
  • Thay đổi vòng lặp chính trong chủ đề giao diện điều khiển đọc của bạn để ngăn chặn trong WaitForMultipleObjects hơn istream::operator>>, một cái gì đó như thế này:

    for (;;) { 
        HANDLE h[2]; 
        h[0] = GetStdHandle(STD_INPUT_HANDLE); 
        h[1] = that_event_object_I_mentioned; 
        DWORD which = WaitForMultipleObjects(2, h, FALSE, INFINITE); 
    
        if (which == WAIT_OBJECT_0) 
         processConsoleCommand(); 
        else if (which == WAIT_OBJECT_0 + 1) 
         break; 
        else 
         abort(); 
    } 
    
  • chủ đề này phải cẩn thận không làm bất cứ hoạt động ngăn chặn khác hơn WaitForMultipleObjects cuộc gọi . Theo thảo luận trong các nhận xét bên dưới, điều đó có nghĩa là processConsoleCommand không thể sử dụng cin. Bạn sẽ cần sử dụng số low-level console input functions thay thế, đặc biệt là GetNumberOfConsoleInputEventsReadConsoleInput, để đảm bảo rằng bạn không chặn; bạn sẽ cần phải tích lũy các ký tự qua nhiều cuộc gọi đến processConsoleCommand cho đến khi bạn đọc trả lại vận chuyển; và bạn cũng sẽ cần phải làm theo tiếng vang của riêng bạn.

+0

Lưu ý rằng việc chặn đầu vào tiêu chuẩn bằng cách sử dụng 'WaitForMultipleObjects()' để tránh việc đọc chặn về cơ bản là không đáng tin cậy. Nếu đầu vào tiêu chuẩn là bàn phím (thiết bị 'CONIN $'), sau đó nhấn bất kỳ phím nào (ngay cả những phím, chẳng hạn như 'CTRL', không tạo đầu vào) sẽ bỏ chặn việc chờ đợi để chặn hoạt động đầu vào tiếp theo vô thời hạn. chủ đề bỏ qua trạng thái của sự kiện. Kiểm tra [câu hỏi liên quan] (http://stackoverflow.com/questions/8347642/checking-win32-file-streams-for-available-input) để biết thêm chi tiết. –

+0

Nó không thực sự quan trọng nếu chủ đề này gió lên spinning thông qua 'WaitForMultipleObjects' khi người dùng đang gõ, miễn là nó đi đúng nhàn rỗi khi người dùng * không * gõ. Tôi muốn nghĩ rằng có một số tương đương với ['FIONREAD'] (http://www.daemon-systems.org/man/ioctl.2.html) có thể được sử dụng để đảm bảo rằng' ReadFile' sẽ không chặn, nhưng Windows đã làm tôi ngạc nhiên với sự vắng mặt của các cơ sở tương tự trước đây. Nếu một cái gì đó như thế này không thể được thực hiện để làm việc, tôi nghĩ rằng tôi muốn nhìn vào thực hiện cửa sổ giao diện điều khiển của riêng tôi với các API GUI. – zwol

+0

... Thảo luận trong câu hỏi liên quan đó không thực sự hữu ích; đề xuất có vẻ là "sử dụng một chuỗi chuyên dụng để đọc từ bảng điều khiển" và ở đây chúng tôi đang thảo luận cách triển khai chính xác một chuỗi như vậy. – zwol