2010-04-22 37 views
6

Tôi có một ứng dụng gồm hai cửa sổ, một giao tiếp với nhau và gửi cho nó cấu trúc có hai số nguyên (Trong trường hợp này là hai cuộn xúc xắc).Làm thế nào để gửi tín hiệu sự kiện thông qua quy trình - C

tôi sẽ sử dụng các sự kiện cho các trường hợp sau:

  • Process một gửi dữ liệu để xử lý b, quá trình b hiển thị dữ liệu
  • Process một đóng cửa, trong quá trình lần lượt đóng cửa b
  • Process b đóng cửa a, lần lượt đóng quá trình a

Tôi đã nhận thấy rằng nếu quá trình thứ hai liên tục chờ quá trình đầu tiên gửi dữ liệu thì chương trình sẽ chỉ ngồi chờ đợi, ich là nơi mà ý tưởng thực hiện các luồng trên mỗi tiến trình đã xảy ra và tôi đã bắt đầu thực hiện điều này.

Vấn đề tôi gặp phải là tôi không có nhiều kinh nghiệm về chủ đề và sự kiện nên tôi không chắc chắn cách tốt nhất để thực sự triển khai những gì tôi muốn làm.

Tôi đang cố gắng tìm hiểu xem quy trình khác sẽ biết về sự kiện được kích hoạt như thế nào để có thể thực hiện các tác vụ cần thực hiện, tôi không hiểu cách một quy trình tách biệt với một quy trình khác nêu rõ các sự kiện đặc biệt vì nó cần hành động ngay khi sự kiện đã thay đổi trạng thái.

Nhờ sự giúp đỡ

Edit:

Tôi chỉ có thể sử dụng Create/Set/phương pháp mở cho các sự kiện, xin lỗi vì đã không nhắc đến nó trước đó.

Hơn nữa, tôi tạo luồng mới trong tiến trình A cho phép người dùng tương tác với ứng dụng trong khi nghe sự kiện đóng.

Tạo chủ đề:

hCreateEventThread = CreateThread(
       NULL,  // lpThreadAttributes (default) 
       0,   // dwStackSize (default) 
       ThreadFunc, // lpStartAddress 
       NULL,  // lpParameter 
       0,   // dwCreationFlags 
       &hCreateEventThreadID // lpThreadId (returned by function) 
       ); 

      if(hCreateEventThread != NULL) 
      { 
       MessageBox(hMainWindow,L"Thread created!",L"Success!",MB_OK); 
      } 

khai mạc sự kiện trên A khi B đóng:

DWORD WINAPI ThreadFunc(LPVOID passedHandle) 
    { 
     hConsumerCloseEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("Global\\ConsumerCloseEvent")); 

     while(TRUE) 
     { 
      dwCloseResult = WaitForSingleObject(hConsumerCloseEvent,INFINITE); 

      switch (dwCloseResult) 
      { 
       // State of object is signalled 
      case WAIT_OBJECT_0: 
       //Consumer has closed, exit program. 
       //CloseHandle(hDiceRoll); 
       //CloseHandle(hCloseEvent); 
       //CloseHandle(hCreateEventThread); 
       ExitProcess(1); 
       break; 
      default: 
       return; 
      } 
     } 
    } 

Tạo sự kiện trong b (Trong WM_CREATE):

hConsumerCloseEvent = CreateEvent( 
       NULL,    // default security attributes 
       TRUE,    // manual-reset event 
       TRUE,    // initial state is nonsignaled 
       TEXT("Global\\ConsumerCloseEvent") // object name 
       ); 

      if(hConsumerCloseEvent == NULL) 
      { 
       MessageBox(hMainWindow,L"CreateEvent failed",L"Error",MB_OK); 
      } 

Thiết sự kiện để báo hiệu khi B đóng:

case WM_DESTROY: 
     { 
      SetEvent(hConsumerCloseEvent); 
      PostQuitMessage(0); 
      break; 
     } 

Như bạn có thể nhìn thấy khi sự kiện được báo hiệu, ứng dụng A được thiết lập để đóng. Khi tôi chạy cả hai ứng dụng và quá trình đóng B, tiến trình A không nhận thấy tín hiệu đã thay đổi và không đóng.

Chỉnh sửa 2:

Sau khi sử dụng các GetLastError(); Tôi đã có thể để xác định rằng tay cầm vào OpenEvent là NULL, sai số nhất định là

ERROR_FILE_NOT_FOUND - 2: Hệ thống không thể tìm thấy các tập tin định

là phương pháp của tôi tạo ra sự kiện và đọc nó không chính xác, tôi đã đảm bảo bao gồm tiền tố Global \.

Trả lời

3

Điều tốt đẹp về các ẩn dụ là chúng đơn phương chăm sóc đồng bộ hóa độ sâu hàng đợi giữa hai quy trình. Vì bạn bị giới hạn sử dụng các đối tượng Sự kiện thay vì tôi khuyên bạn nên có các thông điệp liên tiến trình thay vì một hàng đợi hoặc một hàng đợi nếu bạn muốn.

Process Một

// In the initialization code 
... 
hMessageEmptiedEvent = CreateEvent(NULL, FALSE, TRUE, _T("MessageEmptied")); 
hMessageSentEvent = CreateEvent(NULL, FALSE, FALSE, _T("MessageSent")); 

// Call this function when you want to send the data to process b 
void sendData(struct diceData data) 
{ 
    // Make sure any pre-existing message has been processed 
    WaitForSingleObject(hMessageEmptiedEvent, INFINITE); 
    // Copy the data into the shared buffer 
    *(struct diceData *) pBuf = data; 
    // Signal the other process that data is ready 
    SetEvent(hMessageSentEvnt); 
} 

Process B

// In the initialization code 
... 
hMessageEmptiedEvent = CreateEvent(NULL, FALSE, TRUE, _T("MessageEmptied")); 
hMessageSentEvent = CreateEvent(NULL, FALSE, FALSE, _T("MessageSent")); 

// Call this function when you want to recieve data from process a 
struct diceData readData() 
{ 
    struct diceData data; 

    // Wait for a message to become available 
    WaitForSingleObject(hMessageSentEvent, INFINITE); 
    // Copy the data from the shared buffer 
    data = * (struct diceData *)pBuf; 
    // Signal the other process that message has been read. 
    SetEvent(hMessageEmptiedEvnt); 
} 

Nếu, như tôi đoán, bạn thực sự muốn có một hàng đợi có độ dài hơn một bây giờ bạn có thể thực hiện logic xếp hàng trong quá trình b. Bạn sẽ muốn làm điều đó trong một chủ đề riêng biệt vì một vài lý do. Việc thực hiện logic hàng đợi tùy thuộc vào bạn. Tùy thuộc vào nhu cầu hiệu quả của bạn nó có thể là một mảng tròn hoặc danh sách liên kết hoặc ???.

// In process b's initialzation add a thread to do the queueing 
initializeEmptyQueue(); 
hQueueingThread = CreateThread(NULL, 0, enqueueLoop, NULL, 0, NULL); 


DWORD enqueueLoop(LPVOID ignored) 
{ 
    while (TRUE) 
    { 
    struct diceData data; 
    data = getData(); 
    enqueueData(data); 
    } 
} 
+0

Tôi không hiểu tại sao bạn có các tập hợp sự kiện trùng lặp cho từng mẫu bạn đã cung cấp, cũng như thế nào mỗi quy trình có thể nói rằng người kia đã thay đổi trạng thái ?. Vì một lý do nào đó mặc dù tôi đã đặt sự kiện thành sai, chương trình vẫn thấy nó được báo hiệu ngay lập tức, nó không có ý nghĩa gì cả. –

+0

Thực sự là một bộ gồm hai sự kiện. Lưu ý rằng các tên giống nhau, tiến trình đầu tiên để chạy sẽ tạo ra chúng, cái thứ hai sẽ xử lý các sự kiện đã tồn tại trước đó. Lý do tôi đề nghị sử dụng CreateEvent trong cả hai trường hợp (so với CreateEvent trong một quy trình, và OpenEvent trong một quy trình khác) là nó có nghĩa là không quan trọng bạn bắt đầu quy trình nào trước tiên. Thực tế là các sự kiện được chia sẻ là cách bạn chia sẻ trạng thái. Tôi không biết tại sao bạn lại thấy các sự kiện như luôn được báo hiệu. – torak

+0

Bạn có thể giải thích nó đơn giản hơn không? Các tài liệu MSDN chỉ có xu hướng để hiển thị như thế nào để làm điều đó trong một quá trình, không phải giữa hai vì vậy rất khó hiểu. –

2

Có vẻ như bạn có thể muốn sử dụng CreateSemaphore. Bạn có thể sử dụng một semaphore để đại diện cho số lượng các mục dữ liệu có sẵn cho quá trình b để xử lý. Khởi tạo nó với số lượng là 0, khi một mục dữ liệu được tạo sẵn, tăng nó với ReleaseSemaphore. Sau đó, trong quá trình b, hãy gọi số WaitForSingleObject hoặc một trong số đó, chỉ trả về khi số lượng semaphore vượt quá 0, tại thời điểm đó số đếm được giảm đi.

Đây không phải là giải pháp hoàn chỉnh vì bạn vẫn cần xử lý những việc như phải làm gì khi bộ đệm dùng chung của bạn đầy, nhưng sẽ giúp bạn bắt đầu tốt và thực sự.

+0

Rất tiếc, tôi chỉ bị hạn chế sử dụng các phương pháp CreateEvent/SetEvent vv .., xin lỗi vì đã không đề cập đến nó trong câu hỏi. –

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