문제

내 델파이 응용 프로그램에는 메시지 대기 루프가있는 스레드가 있습니다. 메시지를받을 때마다 일을 시작합니다. 해당 스레드의 실행 절차는 다음과 같습니다.

procedure TMyThread.Execute;
begin
  while GetMessage(Msg, 0, 0, 0) and not Terminated do
  begin
    {thread message}
    if Msg.hwnd = 0 then
    begin
      ...
    end
    else
      DispatchMessage(Msg);
  end;
end;

내 응용 프로그램을 사용하여 일부 테스트를 수행하는 것은 GetMessage 함수가 기본 스레드 의존적이라는 것을 알게되었습니다. 이것은 메인 스레드가 약간의 작업을 수행하는 동안 메시지가 수신되기를 기다리는 경우에도 내 스레드의 getMessage 함수가 반환되지 않는다는 것을 의미합니다 (PostthreadMessage funciton : postMessage (postthreadMessage funciton : postmessage) MythreadId, WM_Mymessage, 0, 0)).

기본 스레드가 작업 또는 응용 프로그램을 완료 할 때만 프로세스 메소드 메소드가 호출되고 GetMessage 리턴을하고 스레드가 작업을 시작합니다. 이런 종류의 스레드 간 통신 구현 나는 내 스레드가 독립적으로 작동 할 것이라고 확신했으며 스레드로 직접 전송 된 메시지 수신이 기본 스레드에 의존 할 것으로 기대하지 않을 것입니다.

테스트를 수행하면 메인 스레드에서 WaitforsingleObject 함수를 사용하여 몇 초 동안 이벤트를 기다렸습니다. 이것은 메시지가 다른 스레드로 전송 되더라도 내 스레드가 작업을 수행하지 않았다는 것을 알았을 때입니다. WaitforsingleObject 함수가 마침내 대기를 마치고 메인 스레드가 유휴 상태가되었을 때, 내 스레드의 getMessage 함수가 반환되었습니다.

누군가 왜 이런 식으로 작동하는지 설명 할 수 있습니까? 그것에 대한 해결 방법이 있습니까? 스레드가 독립적으로 메시지를 받고 싶습니다. 내 모든 스레드는 메인 스레드에 의해 생성됩니다. 이것이 이유일까요?

미리 도움을 주셔서 감사합니다.

마리우스.


MGHIE, 당신은 다시 옳았습니다 (최근에 메시징 물건을 도와주었습니다. 기억할 것입니다). 제안했듯이 GetMessage는 즉시 반환되지만 실제로는 메인 창 메소드를 호출 할 때 스레드가 매달려 있습니다.

procedure TMyThread.Execute;
begin
  while GetMessage(Msg, 0, 0, 0) and not Terminated do
  begin
    {thread message}
    if Msg.hwnd = 0 then
    begin
      ...
      if Assigned(FOnCommEventMethod) then
        FOnCommEventMethod(FCommEventsQueueItem);
      ...
    end
    else
      DispatchMessage(Msg);
  end;
end;

FoncommeventMethod는 '객체의 절차 (Eventmask : Cardinal)'로 선언 된 객체의 방법입니다. (이 스레드는 직렬 포트 이벤트를 처리합니다). 이 경우 FoncommeventMethod에는 기본 양식 클래스에 속하는 절차가 할당되었습니다. 메소드가 내 스레드에 의해 호출되면 스레드는 메인 스레드가 작업을 완료하기를 기다립니다.

어떻게 되나요? 보시다시피, 나는이 절차를 호출하기 위해 synchronize () 메소드를 사용하지 않습니다. 따라서 내 스레드가 기본 스레드와 동기화 될 것으로 기대하지 않습니다. 암시 적으로 발생합니까? BTW, 나는 다른 스레드가 다른 스레드에 의해 액세스되어서는 안된다는 것을 이해하므로 동기화 방법을 사용해야하지만 지금은 몇 가지 빠른 테스트를하고 있습니다.

WaitforsingleObject 주제로 돌아가서, 나는 그것을 사용해서는 안된다는 것을 알고 있지만, (우연히) 문제를 알아 차린 덕분에 단지 테스트였습니다.

당신의 도움을 주셔서 감사합니다. 당신이 나를 도와주지 않았다면, 나는 아마도 메시징을 제거하고 대신 이벤트를 사용 할 것이며, 마지막으로 그것이 이유가 아니라는 것을 알았습니다 :-).

도움이 되었습니까?

해결책

기본 스레드가 작업 또는 응용 프로그램을 완료 할 때만 프로세스 메소드 메소드가 호출되고 GetMessage 리턴을하고 스레드가 작업을 시작합니다.

나는 이것이 실제로 일어나는 일이라고 의심합니다. Afaik 두 개의 메시지 루프는 다른 스레드를 동기화하는 다른 수단을 사용하지 않는 한 서로 독립적이어야합니다. 문자 보내(). 스레드가 실제로 getMessage () 그리고 내부가 아닙니다 동기화 () (사용 중입니다 문자 보내() 내부)?

테스트를 수행하면 메인 스레드에서 WaitforsingleObject 함수를 사용하여 몇 초 동안 이벤트를 기다렸습니다.

당신은 절대 사용해서는 안됩니다 WaitforsingleObject () 100 밀리 초보다 시간이 오래 걸리는 메인 스레드에서는 GUI가 느리게 보이게되므로. 사실 나는 단순히 투표이기 때문에 메인 스레드에서 전혀 사용하지 말라고 조언 할 것입니다. 대신 작업자 스레드에서 메시지를 게시하십시오.

다른 팁

스레드에 대한 메시지 큐를 만들 수 있습니다. 스레드에서 다음 코드를 실행하십시오.

MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
SetEvent(messageQueueReady);
while (GetMessage(&msg, NULL, 0, 0)) 
{
    ...// do message processing here
}

PeekMessage를 호출하면 OS가 스레드에 대한 새 메시지 큐를 만들도록 강요합니다. 이 스레드 (예 : postthreadMessage를 통해)에 메시지를 게시하기 전에 호출이 성공하려면 (예 : WaitforsingleObject를 통해) 기다려야합니다 (예 : WaitforsingleObject를 통해 기다려야합니다). 이것이 위의 예에서 SetEvent API에 대한 호출이있는 이유입니다.

편집하다: 예를 들어 C에있어 죄송합니다. 괜찮기를 바랍니다.

보다 http://groups.google.com/group/borland.public.delphi.language.delphi.win32/browse_thread/thread/cf36834a606321b

증류 요청, 악마가 숨어있는 많은 세부 사항을 남기고 있습니다. 메인 (또는 VCL) 스레드는 델파이에서 특별합니다. 메시지 루프와 같은 것들이 후드 아래의 VCL 스레드와 동기화되는 것 때문에 대기 중입니다. 많은 사람들이 이것에 대한 이론을 가지고 있습니다. 가장 잘 작동하는 것은 VCL 스레드를 최대한 가볍게 유지하여 대기를 최소화하는 것입니다. 모두가 이것에 거의 동의합니다. 어떤 사람들은 효과가있을 수있는 다른 것들에 대한 아이디어를 가지고 있지만 다른 사람들은 단지 문제를 요구하고 있다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top