2008-10-16 3 views
7

사용자가 응용 프로그램을 종료하려고 할 때 IO (HTTP 호출 등)를 수행하는 중 많은 스레드가있는 C++ Win32 응용 프로그램이 있습니다. 현재, 나는 놀고 모든 스레드가 main에서 돌아 오기 전에 끝날 때까지 기다린다. 때로는 이것이 내가 원하는 것보다 오래 걸리는 경우도 있습니다. 실제로 나가기 만하면 사용자를 기다리게하는 것이 무의미한 것처럼 보입니다. 그러나 방금 나가서 main에서 돌아 오면 소멸자가 호출되기 시작하면 오브젝트를 사용하는 스레드가있는 동안 충돌이 발생할 수 있습니다.Win32 앱의 빠른 종료를 어떻게 보장합니까?

이상적으로 미덕의 플라톤 세계에서 가장 좋은 방법은 모든 스레드가 종료 된 다음 정상적으로 종료 될 때까지 기다리는 것입니다. 차세대 실제 솔루션은 무엇입니까? 단순히 스레드를 빠져 나오게하는 것은 옵션이 아닐 수도 있습니다. 목표는 프로세스를 가능한 빨리 종료하여 예를 들어 새 버전을 설치하는 것입니다. 내가하고있는 유일한 디스크 입출력은 트랜잭션 DB에 있기 때문에 플러그를 뽑는 것에 대단히 신경 쓰지는 않습니다.

답변

2

최상의 방법 : 응용 프로그램이 실행되는 동안 작업을 수행하고 시스템 종료시 아무 것도 (또는 너무 가까이서) 작업을 수행하십시오 (시작시에도 작동 함). 그 패턴을 고수하면 종료 요청이 아직 수행해야 할 작업에 대해 걱정하지 않고 즉시 스레드를 즉시 종료 할 수 있습니다.

로컬 작업을 수행하는 경우 특정 상황에서 IO가 완료 될 때까지 기다려야합니다 (적어도 작성해야합니다). HTTP 요청과 같은 당신은 아마 그냥 포기/닫을 수 있습니다 (다시, 당신이 뭔가를 쓰고 있지 않는 한). 그러나이 종료 중에 작성하여 기다리는 경우라면, 래핑하는 동안 프로세스가 멈추는 것처럼 보이기보다는 사용자에게 알릴 수 있습니다.

-5

컴퓨터의 전원 코드를 뽑으라고 지시합니다. 그 짧은 경우, 바람에 비동기 활동을 포기해야합니다. 또는 HWIND입니까? 나는 C++에서 결코 기억할 수 없다. 물론 중간 도로를 타고 텍스트 파일이나 reg 키에 어떤 작업을 신속하게 기록해두고 다음에 프로그램을 실행하면 자동으로 다시 작업을 수행하거나 사용자가 원하는 작업을 수행 할 수 있도록 취소 할 수 있습니다. 비동기 작업을 포기할 때 잃는 데이터에 따라 그 작업을 수행하지 못할 수도 있습니다. 사용자와 상호 작용하는 경우, 왜 그렇게 오래 걸리는지를 설명하는 대화 상자 또는 UI 상호 작용을 고려할 수 있습니다.

저는 개인적으로 컴퓨터의 플러그를 뽑는 것이 좋습니다. :)

+0

웃긴 답을하고, 심연을 따라 내려 가면 ... 사람들은 유머 감각이 없습니다 ... – tloach

+0

그래, 상처 받았어. 어쩌면 그들의 스택이 오버플로되었을 수도 있습니다. –

+1

DIGG 또는 Slashdot는 스레드 응용 프로그램의 경우 -----> – jim

0

플러그를 지저분하게 당기려면 출구 (0)가 트릭을 수행합니다.

+0

IIRC이므로 exit() 대신 _exit()를 호출해야합니다. 나는 이것에 대한 문서를 찾고 있었지만 지금은 찾을 수가 없다. – paxos1977

2

GUI를 사용하고 다른 스레드에서 작업하는 것이 좋습니다. 사용자가 종료를 요청하면 즉시 GUI를 닫아 응용 프로그램이 종료 된 것처럼 보입니다. 작업자 스레드가 백그라운드에서 정상적으로 닫히도록 허용합니다.

+1

"메인 윈도우를 보이지 않는 모드로 설정"한다는 것은 근본 문제를 해결하지 못하고 오직 화장 만하는 것입니다. 게다가 문제는 스레드가 지금 멈추도록 말하고 계속 실행중인 것을 숨기지 않는 것입니다. –

7

I/O를 처리하는 스레드를 항상 제어 할 수 있도록 겹친 IO를 사용하고 언제든지 I/O를 중지 할 수 있습니다. 당신은 IOCP를 기다리면서 애플리케이션 레벨 종료 코드를 게시 할 수 있습니다. 또는 오버랩 된 구조의 이벤트를 기다리고 '모든 스레드를 지금 종료하십시오'이벤트도 기다릴 수 있습니다.

요약하면 취소 할 수없는 통화는 차단하지 마십시오.

차단할 수없는 경우 IO를 수행하는 블로킹 소켓 호출에 걸렸다면 항상 종료 할 시간과 IO를 수행중인 스레드가 항상 확인하도록 결정한 스레드에서 소켓을 닫을 수 있습니다 다시 시도하기 전에 '지금 종료'이벤트 ...

0

Visual Basic 6에도 불구하고 한 번 비슷한 문제가있었습니다. 응용 프로그램의 스레드가 다른 서버에 연결하고 일부 데이터를 다운로드 한 다음 해당 데이터에 대해 반복 작업을 수행하고 결과를 중앙 집중식 서버에 저장합니다.

그런 다음 스레드는 기본 폼에서 정지 할 수 있어야한다는 새로운 요구 사항이있었습니다. 나는 스레드를 N 개의 루프 (약 0.5 초에 해당) 이후에 멈추게하여 특정 이름의 뮤텍스를 열려고 시도하면서 더 쉽지만 더러운 방식으로이 작업을 수행했습니다. 성공했을 때, 그들은 즉시 무엇을하고 있었는지 멈추었 다.

이 뮤텍스는 메인 폼에 의해서만 생성되었습니다. 일단 생성되면 모든 스레드가 곧 닫힙니다. 단점은 스레드를 다시 실행하려는 사용자가 수동으로 지정해야한다는 것이 었습니다. "스레드를 실행할 수 있도록 설정"하는 또 다른 버튼은 뮤텍스를 해제하여 수행했습니다. D

이 트릭은 뮤텍스 연산에 대해 작동하도록 보장됩니다. 문제는 스레드가 실제로 닫혀 있는지 확신 할 수 없다는 것입니다. "openMutex succeeded"를 처리하는 논리에 실패하면 결코 끝나지 않을 수도 있습니다. 또한 모든 스레드가 닫힌 경우 (코드가 맞다고 가정하면 루프가 멈추고 "수신 대기"하는 것과 대략 동일한 시간이 소요될 것입니다).

VB의 "아파트"모델의 멀티 스레딩을 사용하면 스레드에서 주 응용 프로그램으로 정보를주고 받기가 다소 어려우므로 "화재 및 잊어 버리기"가 훨씬 쉬워 지거나 주 응용 프로그램에서만 보낼 수 있습니다 실. 따라서, 이런 종류의 긴 삭감이 필요합니다. C++을 사용하면 멀티 스레딩 모델을 자유롭게 사용할 수 있으므로 이러한 제약 조건이 적용되지 않을 수도 있습니다.

0

무엇을 하든지간에 NOT은 특히 OS HTTP 호출에있을 수있는 모든 항목에서 TerminateThread를 사용하십시오. 재부팅 할 때까지 IE를 깨뜨릴 수 있습니다.

모든 IO를 비동기식 또는 비 차단 모델로 변경하면 종료 이벤트를 볼 수 있습니다.

5

많은 Win32 응용 프로그램에서 저에게 꽤 잘 돌아가는 예외 기반 기술을 사용합니다.

스레드를 종료하려면 QueueUserAPC()을 사용하여 예외를 throw하는 함수에 대한 호출을 대기열에 넣습니다. 그러나 throw 된 예외는 "Exception"유형에서 파생되지 않으므로 내 스레드의 래퍼 프로 시저에서만 catch됩니다. - 즉시가 경보 가능 대기 상태에 들어갈 때, 그것은 APC 기능을 실행 스레드에 필요한

  • 특별한 코드는 'stoppable'도하지 않습니다하기 위해 다음과 같이이의

    장점이다.

  • 모든 소멸자가 예외로 호출되어 스택을 실행하므로 스레드가 정상적으로 종료됩니다.

당신이 조심해야 할 것들 :

  • 아무것도 당신의 예외를 먹을 것이다 catch (...)을하고. 사용자 코드는 항상 catch(const Exception &e) 또는 이와 비슷한 값을 사용해야합니다.
  • I/O 및 지연이 "경고 가능한"방식으로 이루어 졌는지 확인하십시오. 예를 들어, 이는 sleep(N) 대신 sleepex(N, true)을 호출하는 것을 의미합니다.
  • 때때로 CPU 바인딩 된 스레드는 종료를 확인하기 위해 가끔 sleepex(0,true)을 호출해야합니다.

임계 영역에서 작업이 종료되지 않도록 코드 영역을 '보호'할 수도 있습니다.

0

갑자기 종료해야하는 경우 : WinMain에서 돌아 오는 순간 호출되는 ExitProcess 만 호출하면됩니다. Windows 자체는 정리할 방법이없는 많은 작업자 스레드를 생성합니다. 프로세스 종료로 종료됩니다.

어떤 종류의 쓰기를 수행하는 스레드가있는 경우 - 분명히 리소스를 닫을 기회가 필요합니다. 하지만 다른 것은 - 바운스 검사기 경고를 무시하고 양탄자를 발로부터 당깁니다.

0

TerminateProcess를 호출하면 아무에게도 알리지 않고 아무 것도 기다리지 않고 즉시 프로세스를 중지합니다.

0

*NULL = 0이 가장 빠릅니다. 충돌을 원하지 않으면 exit() 또는 해당하는 win32를 호출하십시오.

관련 문제