2014-05-19 24 views
5

Tôi đang cố gắng để có được APC để làm việc trong mã C++ của tôi nhưng tôi không thành công. Tôi bị mất lời. Trong C# nó hoạt động tất cả tốt (hợp lý cùng một mã). Tôi muốn thread 2 để tiêm một cuộc gọi vào thread 1. Nhưng trong dự án C + + của tôi nó sẽ không thực thi vì một lý do nào đó. Tôi đang làm gì sai?Thủ tục không đồng bộ Các cuộc gọi

  • thread 1 (Chủ đề chính)
  • chủ đề 2 (phụ đề, mà cần các chủ đề chính để thực hiện một chức năng)


Code:

#include "stdio.h" 
#include "windows.h" 

#define TIME 2500 
#define LAST_ERROR printf("last error: %i\r\n", GetLastError()); 

HANDLE handle1, handle2; 

void ThreadInfo(char* prefix = "") 
{ 
    printf("%sthread id: %i\r\n", prefix, GetCurrentThreadId()); 
} 

VOID CALLBACK apc(_In_ ULONG_PTR data) 
{ 
    ThreadInfo(" -> apc: 2 -> 1: "); 
} 

void run1() 
{ 
    while (true) 
    { 
     Sleep(TIME); 
     ThreadInfo("1: "); 

     // apc 
     //QueueUserAPC(apc, handle2, (ULONG_PTR) NULL); 
    } 
} 

void run2() 
{ 
    while (true) 
    { 
     Sleep(TIME); 
     ThreadInfo("2: "); 

     // apc 
     QueueUserAPC(apc, handle1, (ULONG_PTR) NULL); 
    } 
} 

void TestThreads() 
{ 
    DWORD threadId; 
    SECURITY_ATTRIBUTES a; 
    a.nLength = 12; 
    a.lpSecurityDescriptor = NULL; 
    a.bInheritHandle = 1; 

    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &handle1, 0, true, 2); 
    LAST_ERROR 

    handle2 = CreateThread(NULL, 100000, (LPTHREAD_START_ROUTINE)run2, NULL, 0, &threadId); 
    printf("handles (1, 2): %i, %i\r\n", handle1, handle2); 
    printf("ids (1, 2): %i, %i\r\n", threadId, GetCurrentThreadId()); 
    printf("--------------------------------\r\n"); 
    run1(); 
} 

int main() 
{ 
    TestThreads(); 

    printf("done."); 
    getchar(); 
    return 0; 
} 

Trả lời

9
Sleep(TIME); 

Đó là statem vấn đề của bạn ent. APC là khá nguy hiểm, họ cho phép tái nhập mã. Các thô tương đương với các tuyên bố nổi tiếng Application.DoEvents() đã nhận được rất nhiều lập trình viên VB gặp rắc rối. Windows không chỉ cho phép chúng chạy, bạn phải là rõ ràng rằng mã của bạn được cấp lại để APC có thể chạy an toàn mà không làm hỏng trạng thái chương trình của bạn.

Yêu cầu cụ thể là chuỗi của bạn đang ở trạng thái chờ "có thể cảnh báo". Đi vào trạng thái chờ không phải là vấn đề, lệnh Sleep() thực hiện điều đó. Tuy nhiên nó không phải là một trạng thái có thể cảnh báo được. Bạn phải sử dụng quyền này thay thế:

SleepEx(TIME, TRUE); 

Sửa đổi hàm run1() trong chương trình thử nghiệm của bạn và bây giờ bạn sẽ thấy gọi lại APC được gọi. So sánh với GetOverlappedResultEx(), SignalObjectAndWait(), WaitForSingleObjectEx() và WaitForMultipleObjectsEx(), các cuộc gọi winapi khác có thể đặt một luồng trong trạng thái chờ cảnh báo. Và có, Thread.Sleep() trong một chương trình quản lý là cảnh báo, CLR gọi SleepEx() dưới mui xe.

+0

Bạn đã ở đâu vài giờ trước? :) Tôi sẽ có ** không bao giờ ** đoán nó là unimposing 'Sleep'. – Bitterblue

+2

Tôi đã ngủ say :) Lời khen ngợi của tôi về mã repro của bạn, mong rằng mỗi người dùng SO sẽ làm cho nó dễ dàng để giúp họ như bạn đã làm. –

+0

Theo [this] (http://stackoverflow.com/a/3783845/1442225) sẽ không có cách nào để tạo một thread _healthy_ GUI để chấp nhận các cuộc gọi APC, đúng không? Tôi phải sử dụng điều này trong MFC ngay bây giờ. – Bitterblue

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