2010-04-22 25 views
6

İki pencereden oluşan bir uygulama var, biri diğerine iletişim kurar ve iki tam sayı içeren bir yapı (Bu durumda iki zar bir zar) gönderir.İşlemler aracılığıyla olay sinyali gönderme - C

aşağıdaki durumlar için olaylar kullanarak olacak

: dönüş kapatma işlemi b

  • İşlem b kapanmaktadır

    • yöntem a b işlemek için veri gönderir, süreç b verileri gösterir
    • işlem bir kapatır, a, sırasıyla, bir kapanış işlemine ilişkin olarak bir

    İkinci işlem sürekli olarak ilk işlemin veri göndermesini beklerse programın beklemede kaldığını fark ettim. Her işlemdeki iş parçacığı uygulama fikri gerçekleşti ve bunu zaten uygulamaya başladım.

    Sorun şu ki, iş parçacığı ve olaylarla çok fazla deneyimim olmadığından, yapmak istediklerimi gerçekleştirmenin en iyi yolundan emin değilim.

    Diğer işlemin ne yapılacağını görmesi için olayın nasıl yapılacağını bilmesini sağlamaya çalışıyorum, bir başkasından ayrı olan bir işlemin nasıl olduğunu anlayamıyorum. Olayların özellikle olay değiştiği anda harekete geçmesi gerektiği gibi olduğunu belirtir. Herhangi bir yardım için

    Teşekkür

    Düzenleme: Ben sadece kullanabilirsiniz

    olaylar için/Set/Açık yöntemleri oluşturma, daha önce söz için özür.

    Ayrıca, A olayında, kullanıcının yakın olayı dinlerken uygulama ile etkileşimde bulunmasına olanak veren yeni bir iş parçacığı oluşturuyorum.

    oluşturma ipliği: B kapatır A

    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); 
          } 
    

    açma olayı (WM_CREATE olarak b) 'de

    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; 
          } 
         } 
        } 
    

    oluşturma olayı:

    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); 
          } 
    
    B kapandığında sinyal olay Ayar

    : Olay sinyal verilmesi durumunda, uygulama A kapatmak için ayarlanır görebileceğiniz gibi

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

    . Her iki uygulamayı çalıştırdığımda ve B işlemini kapattığımda, A işlemi değiştirilen sinyali fark etmez ve kapanmaz.

    Düzenleme 2:

    GetLastError() kullanılması; Ben OpenEvent için tanıtıcı NULL olduğunu tespit edebildi, verilen hata

    ERROR_FILE_NOT_FOUND olduğunu - 2: dosyayı bulamıyor sistem belirtilen

    mi etkinliği oluştururken benim yöntemi ve Yanlış okumak, Global \ prefix'i dahil ettiğinizden emin oldum.

  • cevap

    3

    Semaforlar ile ilgili güzel olan şey, iki işlem arasındaki sıra derinliğini senkronize etmenin tek başına ele almalarıdır. Etkinlik nesnelerini kullanmayla sınırlı olduğunuz için, bir sıra yerine süreçler arası iletilere sahip olmanızı veya isterseniz bir kuyruğunun olmasını öneririm.

    Süreç A

    // 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); 
    } 
    

    Proses 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); 
    } 
    

    Ben tahmin ediyorum, sen aslında şimdi kuyruk mantığı uygulayabilirsiniz birden fazla uzunlukta bir kuyruk olsun istiyorum, Eğer süreç b. Bunu birkaç sebepten dolayı ayrı bir iş parçacığında yapmak isteyeceksiniz. Kuyruk mantığının uygulanması size kalmış. Verimlilik ihtiyaçlarınıza bağlı olarak dairesel bir dizi veya bağlantılı bir liste olabilir veya ???.

    // 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

    Sağladığınız her örnek için niçin yinelenen olaylar kümeniz olduğunu anlamıyorum, ayrıca her işlemin diğerinin durumu değiştirdiğini nasıl anlatabilirim? Herhangi bir sebepten dolayı, olayı yanlış olarak ayarladığım halde, programın hala sinyal verildiğini görürsünüz, bu hiç mantıklı değil. –

    +0

    Aslında bir iki olay kümesi. Adların aynı olduğuna dikkat edin, ilk işlem, bunları oluşturacak, ikincisi ise önceden varolan olayların bir tanıtıcısını alacaktır. Her iki durumda da CreateEvent'in kullanılmasını önerdiğim neden (bir işlemde CreateEvent ve diğerinde OpenEvent ile karşılaştırıldığında), hangi işlemin ilk başladığının önemli olmadığı anlamına gelmesidir. Etkinliklerin paylaşıldığı gerçeği, devleti nasıl paylaştığınızdır. Olayları her zaman olduğu gibi niçin görüyorsun bilmiyorum. – torak

    +0

    Bunu daha açıklayabilir misiniz? MSDN belgeleri yalnızca bir süreçte nasıl yapılacağını gösterme eğilimindedir, ikisi arasında değil, anlaşılması güçtür. –

    2

    CreateSemaphore'u kullanmak isteyebilirsiniz. İşlenecek işlem b için kullanılabilen veri öğelerinin sayısını göstermek için bir semafor kullanabilirsiniz. Bir veri öğesi ReleaseSemaphore ile artırılarak kullanılabilir hale getirildiğinde, onu 0 olarak sayın. Daha sonra işleminizde b WaitForSingleObject numaralı telefonu arayın veya sadece bir semender sayısı 0 olduğunda, bu sayede sayım azaltılır.

    Bu, tam bir çözüm değil çünkü paylaşılan arabelleğiniz dolduğunda yapılması gerekenler gibi işlem yapmanız gerekiyor, ancak sizi iyi ve gerçekten başlatmanız gerekiyor.

    +0

    Ne yazık ki, yalnızca CreateEvent/SetEvent vb. Kullanarak kısıtlıyorum. –

    İlgili konular