2009-12-16 4 views
0

차단 방법이 있다고 가정 해 봅시다. Block()을 호출합니다.스레드 동기화

내가 메인 스레드를 차단하고 싶지 않아 대신 작업자 스레드를 생성 할 수 있습니다. 대신 블록을 호출합니다.

그러나 다른 조건이 있습니다.

5 초 이내에 블록 호출을 반환하고 싶습니다. 그렇지 않으면, 주 스레드가 차단 호출을 알리고 작업자 스레드를 종료하도록하고 싶습니다.

그 시나리오에서 가장 좋은 해결책은 무엇입니까?

내가 그런 식으로 뭔가를 생각 : 5 초, 및 추가 전과 블록에 대한 호출 후 GetTickCount를 호출하고 델타를 계산하기에 타이머 객체를 생성하기 위해 작업자 스레드에서하는 workher 스레드를 만들 수 있습니다.

또한 Block 함수가 이미 반환되었는지 여부를 나타내는 IsReturned 부울을 정의합니다. 블록 호출 후 을 true로 설정하십시오.

는 타이머 기능의 해당 부울에 따라 내가 진행하는 방법을 결정 : 부울이 참

  1. 경우 내가 아무것도하지 않습니다.

  2. 부울 내가이 APC OnFailure 대기 또는

  3. (건 내가 그렇게 할 수 있는지 확실하지 않습니다이다) 어쩌면 주 스레드에서 성공 이벤트를 신호 및 forcfully 작업자 스레드를 종료 할 수 있습니다 false 인 경우

또한 블록 함수가 반환 된 후에 델타가 렛트인지 확인한 다음 5 초 인지 확인하고 APC OnSucess를 대기시킵니다. (질문은 종료합니까 호출자 스레드가 타이머도 취소합니까? 기본적으로 타이머가 쓸모 없다는 이유로)

ps - 내가 타이머 함수 내에서 작업자 스레드를 취소 할 수 있는지를 알 수 있다면 나는 심지어 gettickcount 물건이 필요하다고 생각해.

감사합니다.

+1

어떤 스레딩 API를 사용하고 있습니까? Pthreads? 스레드를 늘리시겠습니까? – mch

+3

이 차단 방법은 무엇을합니까? 당신은 Windows 입출력 완료 포트 및 SleepEX()를 활용할 수 있습니까? –

+0

windows? 리눅스? 맥 OS? –

답변

2

나는 이것을 위해 boost :: threads 라이브러리를 사용할 것을 제안합니다. 차단 스레드가 결합 가능한지 (즉, 여전히 작동하는지) 주기적으로 확인한 다음 5 초 후에 중단 할 수 있습니다. 그런 다음 차단 기능을 작성하여 중단을 처리하고 완전히 종료하십시오.

#include <boost/thread/thread.hpp> 

void Block(void) 
{ 
    //Do work and periodically call boost::this_thread::sleep() 
    try 
    { 
     boost::this_thread::sleep(boost::posix_time::milliseconds(100)); 
    } 
    catch(boost::thread_interrupted const&) 
    { 
     return; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    boost::thread blockThread(Block); //If Block takes arguments, just add them as arguments to the constructor. 
    time_t startTime = time(NULL); 

    while(true) 
    { 
     if(blockThread.joinable() && (time(NULL) - startTime) > 5) 
     { 
      blockThread.interrupt(); 
     } 
     //Do whatever you want while waiting for the thread to finish. 
    } 
} 

편집 : 부스트 스레드 클래스에 대한 더 중단 점에 대한 Thread Management 문서와 정의를 확인하십시오.

편집 2 : 차단 스레드가 완료 될 때까지 기다리는 동안 주 스레드에서 작업을 수행 할 필요가 없으며 Block()에서 인터럽트를 처리 할 편리한 곳이 없으면 다음과 같이 스레드를 명시 적으로 종료 할 수 있습니다. :

void Block(void) 
{ 
    //Do work 
} 

int main(args) 
{ 
    boost::thread blockThread(Block); 

    //timed_join() returns false if the thread is still running after the specified time. 
    if(!blockThread.timed_join(boost::posix_time::milliseconds(5000))) 
    { //detach() will kill the thread, any memory initialised in Block() will not be freed, any locals may or may not be freed either. 
     blockThread.detach(); 
    } 
} 
2

대략적인 아이디어가 있다고 생각합니다. WM_TIMER 메시지가 잠재적으로 차단 스레드가 아닌 주 스레드로 전달되기를 원합니다. 그렇지 않으면 타이머가 시작되기 전에 스레드가 차단되면 타이머 메시지가 손실 될 수 있습니다. 마찬가지로, 작업자가 아닌 주 스레드의 경과 시간을 확인하십시오. Block() 블록이 반환되지 않으면 GetTickCount() (Block()) 이후의 호출은 절대 발생하지 않으므로 검사하십시오.

스레드간에 통신하려면 가장 간단한 방법은 원자 변수를 사용하는 것입니다. 또한 작업자가 성공하면 주 스레드에게 메시지를 다시 전달할 수 있으며 5 초 타이머가 실행될 때 주 스레드가 메시지를 볼 수 없으면 작업자 스레드가 차단 된 것으로 가정해야합니다.

일반적으로 차단 된 스레드를 죽이는 것은 위험 할 수 있습니다. 자바 문서는 그것을하는 것에 강하게주의를 기울이고, 무엇보다도 문제는 C++에서 더욱 심각하다. 자신을 경고한다고 생각하십시오!

0

처음 스레드를 만드는 것은 비용이 많이 들기 때문에 Block을 호출 할 때마다 수행하는 것이 좋습니다.

두 번째로이 문제를 해결할 수있는 다양한 방법이 있으며, 이는 또한 환경에 크게 좌우됩니다. 예를 들어 Windows에서이 작업을 수행 할 수있는 방법은 작업 큐에 메시지 큐가있는 작업자 스레드를 만드는 것입니다. 그런 다음 작업자 스레드에서 처리하는 몇 가지 메시지를 정의합니다. 하나는 WM_CALLBLOCK이 될 수 있습니다. 다른 하나는 WM_AREYOURADY와 WM_YESIAM이 될 수 있습니다. 그러면 Block()을 호출 할 때 해당 메시지를 작업자 스레드에 게시하고 함수를 호출 할 수 있습니다. 메시지를 사용하여 Block()에 필요한 매개 변수를 전달할 수도 있습니다. 함수가 블로킹 중이므로 WM_AREYOURADYY 메시지를 게시하면 WM_YESIAM 응답을 직접받지 못합니다. 그래서 시간 제한을 세울 수 있습니다.