Pergunta

Há um fio na minha aplicação Delphi que tem um loop de mensagem em espera. Cada vez que recebe uma mensagem, ela começa a fazer algum trabalho. Aqui é o procedimento executar desse tópico:

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;

Fazendo alguns testes usando meu aplicativo eu descobri que a função GetMessage é thread principal dependente. Com isto quero dizer que, enquanto o thread principal está fazendo algum trabalho, a função GetMessage no meu segmento não retornar, mesmo que uma mensagem está aguardando para ser recebido por ele (a mensagem é enviada por um outro segmento usando o funciton PostThreadMessage: PostMessage ( MyThreadId, WM_MYMESSAGE, 0, 0)).

Somente quando o segmento principal termina seu trabalho ou o método Application.ProcessMessages é chamado, faz GetMessage retorno e meu fio começa a fazer o seu trabalho. Implementar este tipo de comunicação inter-thread eu tinha certeza de que os meus tópicos iria trabalhar de forma independente e eu nunca esperaria que a recepção de mensagens enviadas diretamente para um fio seria dependente do thread principal.

Fazendo os testes que eu usei a função WaitForSingleObject no segmento principal, à espera de um evento por alguns segundos. Isto é, quando eu notei que meu segmento não estava fazendo qualquer trabalho mesmo que as mensagens foram enviadas a ele por outro segmento. Quando a função WaitForSingleObject, finalmente, espera terminou e o segmento principal se tornou ocioso, a função GetMessage no meu segmento retornado.

Alguém poderia me explicar por que ele funciona dessa maneira? Existe uma solução para isso? Eu gostaria de fazer o meu fio de receber mensagens de forma independente. Todos os meus tópicos são criados pelo thread principal. Que este seja o motivo?

Obrigado por sua ajuda com antecedência.

Mariusz.


Mghie, você estava absolutamente certo de novo (que me ajudou com o material de mensagens ultimamente, você pode se lembrar). Como você sugeriu, GetMessage retorna imediatamente, mas os trava rosca, de fato, em uma chamada a um método janela principal:

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 é um método de objeto, declarado como 'procedimento (EventMask: Cardinal) do objeto;' (Esta discussão trata os eventos de porta serial). Neste caso, o FOnCommEventMethod foi atribuído um procedimento pertencente à classe principal forma. Quando o método é chamado pelo meu fio, os trava rosca esperando a thread principal para terminar o seu trabalho.

Como assim? Como você pode ver, eu não usar o método Synchronize () para chamar este procedimento. Portanto, eu não esperaria que o meu segmento a ser sincronizado com o segmento principal. Isso acontece implicitamente? BTW, eu entendo que todos os componentes da GUI não devem ser acessados ??por quaisquer outros tópicos, mas o principal, de modo que o método Sincronizar deve ser usado, mas eu só estou fazendo alguns testes rápidos agora.

Chegando de volta ao assunto WaitForSingleObject, eu sei que não deveria usá-lo, mas foi apenas um teste graças à qual (coincidentemente) eu notei o problema.

Obrigado por sua ajuda. Se você não me ajudar, eu provavelmente iria se livrar de eventos de mensagens e usar em vez disso, e, finalmente, eu iria notar que não era a razão: -).

Foi útil?

Solução

Somente quando o segmento principal termina seu trabalho ou o método Application.ProcessMessages é chamado, faz GetMessage retorno e meu fio começa a fazer o seu trabalho.

Eu duvido que este é realmente o que está acontecendo. AFAIK os dois loops de mensagens devem ser independentes uns dos outros, contanto que você não utilizar outros meios de sincronização dos tópicos, como SendMessage () . Tem a certeza de que a linha de fato bloquear dentro de GetMessage () e não dentro de Sincronizar () (que está usando SendMessage () internamente )?

Fazendo os testes que eu usei a função WaitForSingleObject no segmento principal, à espera de um evento por alguns segundos.

Você nunca deve usar WaitForSingleObject () no segmento principal com um tempo limite maior do que, digamos, 100 milissegundos, pois isso fará com que seu GUI parecer lento. Na verdade, eu o aconselharia a não usá-lo em tudo no segmento principal, porque isso é simplesmente polling. Postar uma mensagem do seu segmento de trabalho em seu lugar.

Outras dicas

Você pode criar uma fila de mensagens para seu segmento. Basta executar o seguinte código no seu segmento:

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

A chamada para PeekMessage força o OS para criar uma nova fila de mensagens para seu segmento. Você tem que ter certeza para sincronizar esta, ou seja, você tem que esperar (por exemplo através de WaitForSingleObject) para a chamada para ter sucesso antes de enviar mensagens para esta discussão (por exemplo, via PostThreadMessage). É por isso que há uma chamada para a API SetEvent no exemplo acima.

Editar:. Desculpe o exemplo de estar em C, a esperança de que é ok para você

Consulte http: // groups.google.com/group/borland.public.delphi.language.delphi.win32/browse_thread/thread/cf368834a606321b

destilação requerido, deixando de fora muitos detalhes gnarly em que as peles diabo: o segmento principal (ou VCL) é especial em Delphi, porque muitas coisas sob o capô não são thread-safe, e possui todos eles. Coisas como o vento mensagem de loop se espera por causa de coisas que sincronizar com o segmento VCL sob o capô. Muitas pessoas têm teorias sobre isso. A única coisa que parece funcionar melhor é manter seu segmento VCL como a luz / ágil possível para minimizar espera. Todo mundo praticamente concorda com isso. Algumas pessoas têm idéias sobre outras coisas que o trabalho força, mas as outras pessoas pensam que estão apenas pedindo para ter problemas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top