none
[問題] 關於使用WaitForMultipleObjects搭配SetEvent的問題 RRS feed

  • 問題

  • 各位前輩大家好,小弟寫了一個很簡單的測試程式,發現了掉event的現象,想請問有沒有更好的寫法或是解決方法

    開發環境:VS2005

    測試環境:WM6.1

     

    (1) Create 5個event,g_hTest是一個有5個handle的array

    Code Snippet
    HANDLE g_hTest[5] = {0};
        g_hTest[0] = CreateEvent(NULL, FALSE, FALSE, _T("event0"));
        g_hTest[1] = CreateEvent(NULL, FALSE, FALSE, _T("event1"));
        g_hTest[2] = CreateEvent(NULL, FALSE, FALSE, _T("event2"));
        g_hTest[3] = CreateEvent(NULL, FALSE, FALSE, _T("event3"));
        g_hTest[4] = CreateEvent(NULL, FALSE, FALSE, _T("event4"));

     

     

     

    (2) 下面這一段是我的test thread:(ShowText是個把訊息貼上ListBox的function)

    Code Snippet

     

    DWORD test_thread(LPVOID lp)
    {
        HWND hWnd = (HWND)lp;
        DWORD dwObj = 0;
        int nEventNum = 0;
        nEventNum = dim(g_hTest);

        while(g_bTest)
        {
            dwObj = WaitForMultipleObjects(nEventNum, g_hTest, FALSE, INFINITE);
            switch(dwObj)
            {
            case WAIT_OBJECT_0: //event0
                {
                    ShowText(hWnd, L"(%d)event0\n", GetTickCount());
                    break;
                }
            case WAIT_OBJECT_0+1: //event1
                {
                    ShowText(hWnd, L"(%d)event1\n", GetTickCount());
                    break;
                }
            case WAIT_OBJECT_0+2: //event2
                {
                    ShowText(hWnd, L"(%d)event2\n", GetTickCount());
                    break;
                }
            case WAIT_OBJECT_0+3: //event3

                {
                    ShowText(hWnd, L"(%d)event3\n", GetTickCount());
                    break;
                }
            case WAIT_OBJECT_0+4: //Exit
                {
                    g_bTest = false;
                    break;
                }
            default:
                {
                    ShowText(hWnd, L"(%d)default", GetTickCount());
                    break;
                }
            }
        }

        return TRUE;
    }

     

     

    (3) 我在某一個按鈕按下去後,連續執行好幾個SetEvent如下:

    Code Snippet

        SetEvent(g_hTest[0]);
        SetEvent(g_hTest[1]);
        SetEvent(g_hTest[2]);
        SetEvent(g_hTest[3]);
        SetEvent(g_hTest[0]);
        SetEvent(g_hTest[1]);
        SetEvent(g_hTest[2]);
        SetEvent(g_hTest[3]);
       

     

    當我按下按鈕後,連續Set 8個Event,不過ShowText顯現的訊息為:

    (690054)event0

    (690247)event0

    (690286)event1

    (690296)event2

    (690307)event3

     

    請問一下,中間還有3個event1/2/3都不見了,是寫法有需要改?還是這是limitation呢?

    如果是limitation,不知道各位前輩有建議改寫成另外的寫法?

    PS. 試過用WaitForSingleObject,也是類似的問題

    內容很多,感謝您耐心的看完這篇文章,謝謝~~

    2008年6月30日 上午 02:02

解答

  • WaitForMultipleObjects 參數的確無法正確的在 CE 下工作,請參考以下使用 WaitForSingleObject 來做的程式碼:

     

    DWORD MyWaitForMultipleObjects(DWORD count, const HANDLE *lpHandles,
          BOOL waitAll, DWORD ms)
    {
    #ifdef _WIN32_WCE
     if (!waitAll)
      return WaitForMultipleObjects(count, lpHandles, waitAll, ms);
     else
     {
      // wait for each in turn. Note that this does not exactly simulate
      // WaitForMultipleObjects, as each object will become signalled as
      // soon as WaitForSingleObjects recognizes it, rather than all becoming
      // signaled together as with WaitForMultipleObjects...
      DWORD ret = WAIT_OBJECT_0;
      for (DWORD n = 0;n < count;n++)
      {
       DWORD d;
       d = WaitForSingleObject(lpHandlesNo, ms);
       if (WAIT_TIMEOUT == d)
       {
        ret = WAIT_TIMEOUT;
        break;
       }
       else if (WAIT_ABANDONED == d)
       {
        ret = WAIT_ABANDONED_0 + n;
        break;
       }
      }

      return ret;
     }
    #else
     return WaitForMultipleObjects(count, lpHandles, waitAll, ms);
    #endif

    }
    2008年7月29日 上午 09:12

所有回覆

  • 不是訊息漏掉,是您的程式寫錯..

     

    WaitForMultipleObjects (

    DWORD nCount,

    CONST HANDEL* lpHandles,

    BOOL bWatiAll,

    DWORD dwMilliseconds

    );

     

    其中第三個參數設定為 TRUE 會等待所有執行緒都被激發後才會往下,

    您的程式裡面設定的是 FALSE..

     

    2008年7月14日 上午 06:52
  • Hi Chaojen,

     

    因為我的project環境是在Windows Mobile底下,所以如果查MSDN範圍「Smart Device Development」,他的fWaitAll參數解釋如下:

     

    Code Snippet
    fWaitAll
    [in] Specifies the wait type. This parameter must be set to FALSE. This causes function to return when the state of any one of the objects set to is signaled. The return value indicates the object whose state caused the function to return.

     

     

    所以我才會用FALSE當作參數帶入,我剛剛試了一下帶TRUE進去,好像不會wait了,test_thread裡面的ShowText會一直跑,無法跟SetEvent作搭配使用。

    不知道是不是我觀念有誤,或是Chaojen大大有另外的看法可以建議我,非常感謝您。

     

    PS. 我的應用是需要test_thread去針對每個SetEvent作個別的動作,但是因為實際狀況,每個SetEvent之間的間隔時間有可能會非常的短,所以我才發現這個掉event的狀況,關於我最上面的連續SetEvent按鈕動作,只是為了模擬真實狀況,所以不一定是0-1-2-3的順序觸發,在這邊稍微澄清一下,如果造成誤解的話不好意思。

    2008年7月14日 下午 01:25
  • WaitForMultipleObjects 參數的確無法正確的在 CE 下工作,請參考以下使用 WaitForSingleObject 來做的程式碼:

     

    DWORD MyWaitForMultipleObjects(DWORD count, const HANDLE *lpHandles,
          BOOL waitAll, DWORD ms)
    {
    #ifdef _WIN32_WCE
     if (!waitAll)
      return WaitForMultipleObjects(count, lpHandles, waitAll, ms);
     else
     {
      // wait for each in turn. Note that this does not exactly simulate
      // WaitForMultipleObjects, as each object will become signalled as
      // soon as WaitForSingleObjects recognizes it, rather than all becoming
      // signaled together as with WaitForMultipleObjects...
      DWORD ret = WAIT_OBJECT_0;
      for (DWORD n = 0;n < count;n++)
      {
       DWORD d;
       d = WaitForSingleObject(lpHandlesNo, ms);
       if (WAIT_TIMEOUT == d)
       {
        ret = WAIT_TIMEOUT;
        break;
       }
       else if (WAIT_ABANDONED == d)
       {
        ret = WAIT_ABANDONED_0 + n;
        break;
       }
      }

      return ret;
     }
    #else
     return WaitForMultipleObjects(count, lpHandles, waitAll, ms);
    #endif

    }
    2008年7月29日 上午 09:12
  • Hi Chaojen,

    謝謝你的sample code,我會去try看看

    感謝

    2008年7月30日 上午 03:52
  •  

    Hi,

     

    WinCE的確不能使用WaitForMultipleObjects, 我寫過類似的程式, 不過是利用同一個Event handle但是註冊不同的callback function。你可以先在不同按鈕事件註冊不同的callback function

    然後在你的執行緒程式或中斷副程式中,執行相對應的程式

    dwStatus = WaitForSingleObject( hISTInterruptEvent, INFINITE);
      
      if( dwStatus == WAIT_OBJECT_0 )
      {

     

        if (flag & 0x01)

        //Do Something...

        //Callback functon1

        if (flag & 0x02)
        //Do Something...

        //Callback functon2    
        if ( (flag & 0x04) 

        //Do Something...

        //Callback functon3     

       if ( (flag & 0x08) 

       //Do Something...

       //Callback functon4

     

        }

     

    如果你的程式有搭配硬體實作,flag可以當作不同按鈕的事件,0x01~0x08則為實際的不同按鈕觸發的狀態暫存器狀態值

     

    flyball

    2008年8月21日 上午 08:00
  • 請將 test_thread 的 priority 提高, 或是加入 Sleep(100); 等 code 在 SetEvent 之間.

     

    2008年10月24日 上午 03:42