ukk1211
1k
2020-10-21 22:23:06
2
191

쓰레드 동기화 waitfor~관련함수 질문입니다.



int g_int =0;
UINT ThreadA(LPVOID param)
{
   for(int i=0; i<100; i++)
      g_int+=i;
    return 0;
    
}

UINT ThreadB(LPVOID param)
{
    for(int j=0; j<100; j++)
       g_int-=j;

    return 0;
}


void MYApp::InitInstance()
{
    CWinThread * threadA = afxBeginThread(ThreadA,NULL);
    CWinThread * threadB = afxBeginThread(ThreadB,NULL);

    HANDLE m_handle[2] = {threadA->m_hThread,threadB->m_hThread};

    WaitForMultipleObjects(2,m_handle,TRUE,INFINITE);

    ......이하 함수.....
}

위와 같이 MFC 응용프로그램 App 클래스의 인스턴스 초기화 부분에서 WaitForMultipleObjects

함수를 사용하였는데 원래대로면 g_int 값이 0이 되고 ThreadA와 ThreadB가 return 하여야만

WaitForMultipleObjects가 리턴하도록 의도하였습니다.

그러나 WaitForMultipleObjects함수가 Thread A와 B 모두 끝나기 전에 리턴해버립니다...

WaitForMultipleObjects 직후

GetLastError을 통해 확인해보니 에러코드 6(Invalid Handle)가 뜨거나 또 어떤 타이밍엔 87(파라미터 에러)가 
뜹니다...

구글링을 통해 HANDLE 을 new 동적할당하여 해보았지만 여전히 바로 WaitForMultipleObjects 함수가 리턴해버립니다.

WaitForMultipleObjects리턴하고 ThreadB가 실행이돼서 제가 의도한 로직과 전혀 다르게 움직이고 있습니다.;;;

또 ThreadA다음 바로 ThreadB를 시작하는데도 ThreadA만 모두 실행되버리고 ThreadB는 WaitForMultipleObjects이 바로 리턴하고 그 직후 실행되기도 합니다..

멀티쓰레드 동기화 관련테스트를 하다가 우연히 발견한 에러입니다.

ThreadA와 B 모두 로직 실행후 WaitForMultipleObjects가 리턴하도록 하는게 목적입니다.

조언해주시면 감사하겠습니다!





0
  • 답변 2

  • Mete5
    242
    2020-10-21 23:41:06 작성 2020-10-21 23:45:47 수정됨

    일단 WaitFor~ 함수가 먹지 않는건 WaitFor 함수 시작 전 스레드가 종료되기 때문일겁니다.

    Afx로 실행한 스레드는 종료되면서 CWinThread 내부 핸들 값이 날라가구요.

    CWinThread * threadA = AfxBeginThread(ThreadA, NULL, NULL, NULL, CREATE_SUSPENDED);

    CWinThread * threadB = AfxBeginThread(ThreadB, NULL, NULL, NULL, CREATE_SUSPENDED);

    threadA->m_bAutoDelete = FALSE;

    threadB->m_bAutoDelete = FALSE;

      threadA->ResumeThread();

      threadB->ResumeThread();


    이렇게 써도 되고, 아니면 _비긴스레드ex 써도 되고, 자세한건 AfxBeginThread 종료 시점에 대해서 찾아보시길 추천드립니다.


    그리고 일부러 전역변수를 스레드 내부에 쓰신건진 모르겠는데, 의도하신바가 아니라면 CS나 뮤텍스정돈 걸어주시는게 좋을 것 같습니다. 


    100번이 아니라 값이 아주 크게 늘어나면 하다못해 Sleep(1)정도라도..


    AfxThread도 내부적으로 _beginthread를 쓰고, 뭐 MFC에선 Afx스레드, 일반적으로 _beginthread를 쓰라고 하는데, 저도 MFC 쓰는 입장이지만 UI같이 유저 인터페이스단 처리하는 것 아니면(메세지매핑 필요 등) _begin 자주 사용하게 되더라구요

  • ukk1211
    1k
    2020-10-22 16:46:07 작성 2020-10-22 16:59:49 수정됨

    @Mete5

    답변 감사합니다.

    UINT ThreadA(LPVOID param)
    {
      while(1)
      {
          Sleep(1);
      }
        
    }
    
    UINT ThreadB(LPVOID param)
    {
    
        return 0;
    }
    같은 조건에서 위와같이 B를 바로 리턴해버리도록 수정했는데 WaitForMultipleObjects가 적용됩니다...
    리턴하지 않아요. 
    UINT ThreadA(LPVOID param)
    {
      return 0;
    }
    
    UINT ThreadB(LPVOID param)
    {
        while(1)
        {
           Sleep(1);
        }
    }
    반대로하면 WaitForMultipleObjects 적용되지 않고 리턴해버립니다. ThreadB가 절대 끝나지 않고 INFINITE로 
    모두 리턴할때까지 기다려야하는데 순서만 바꿨다고 정반대의 결과가 나옵니다.
    afxBeginThread를 A쓰레드부터 시작해서 그럴까요?
    ThreadA 다음 바로 ThreadB를 시작한건데 뭐가 문제일까요?
    +뭔지 알았습니다. waitfor~전에 Sleep(1) 주니까 항상 waitfor이 리턴하네요..
    쓰레드가 시작하려면 생각보다 시간이 많이 걸리나봅니다
  • 로그인을 하시면 답변을 등록할 수 있습니다.