Frage

Es ist ein Thread in meiner Delphi-Anwendung, die eine Nachricht-Warteschleife hat. Jedes Mal, es eine Nachricht empfängt, beginnt es einige Arbeit zu tun. Hier ist die Prozedur ausführen dieses Themas:

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;

Doing einige Tests meine Anwendung entdeckte ich, dass die GetMessage Funktion Haupt-Thread abhängig ist. Damit meine ich, dass während des Haupt-Thread einige Arbeit tut, die GetMessage-Funktion in meinem Thread auch dann nicht zurückkehren, obwohl eine Nachricht von ihr zu empfangen wartet (die Nachricht von einem weiteren Thread gesendet wird, um die Postthreadmessage funciton mit: Postmessage ( MyThreadId, WM_MyMessage, 0, 0)).

Erst wenn der Haupt-Thread seine Arbeit oder das Application.ProcessMessages Verfahren beendet genannt wird, tut GetMessage Rückkehr und mein Thread seine Arbeit beginnt zu tun. Die Umsetzung dieser Art von inter-thread Kommunikation war ich sicher, dass meine Threads unabhängig funktionieren würde, und ich würde nie erwarten, dass der Empfang von Nachrichten direkt an einen Thread gesendet auf dem Haupt-Thread abhängig sein würde.

Doing die Tests ich die WaitForSingleObject Funktion im Hauptthread verwendet, für ein paar Sekunden auf ein Ereignis warten. Dies ist, wenn ich merkte, dass mein Thread nicht war keine Arbeit selbst zu tun, obwohl Nachrichten von einem anderen Thread zu ihm geschickt wurden. Wenn schließlich die WaitForSingleObject Funktion beendet Warten und der Haupt-Thread wurde im Leerlauf, die GetMessage-Funktion in meinem Thread zurückgegeben.

Könnte mir jemand erklären, warum es so funktioniert? Gibt es eine Abhilfe zu, dass? Ich möchte meinen Thread Nachrichten unabhängig empfangen machen. Alle meine Fäden werden von der Haupt-Thread erstellt. Kann dies der Grund sein?

Vielen Dank für Ihre Hilfe im Voraus.

Mariusz.


mghie, waren Sie absolut richtig wieder (Sie haben mich in letzter Zeit mit dem Messaging-Sachen geholfen, Sie erinnern sich vielleicht). Wie Sie vorgeschlagen, kehrt GetMessage sofort, aber der Faden hängt, in der Tat, auf einem Aufruf an ein Hauptfenster Methode:

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 ist ein Verfahren zum Gegenstand, deklariert als 'Verfahren (EventMask: Cardinal) des Gegenstandes;' (Dieses Thema behandelt serielle Schnittstelle Ereignisse). In diesem Fall wurde die FOnCommEventMethod eine Prozedur, die zu der Hauptform Klasse zugeordnet. Wenn das Verfahren von meinem Thread aufgerufen wird, hängt der Thread für den Haupt-Thread wartet seine Arbeit zu beenden.

Wie kommt das? Wie Sie sehen können, verwende ich nicht das Synchronisieren () Methode, um dieses Verfahren zu nennen. Deshalb würde ich nicht erwarten, mein Thread mit dem Haupt-Thread zu synchronisieren. Ist es implizit geschehen? BTW, ich verstehe, dass alle GUI-Komponenten sollen nicht von anderen Threads zugegriffen werden, aber die wichtigsten, so dass die Synchronisierungsmethode verwendet werden soll, aber ich bin jetzt nur ein paar schnellen Tests zu tun.

zurück zum Thema WaitForSingleObject Comming, ich weiß, ich soll es nicht verwenden, aber es war nur ein Test dank denen (zufälligerweise) ich das Problem bemerkt.

Danke für Ihre Hilfe. Wenn Sie mir nicht helfen würden, würde ich wahrscheinlich loswerden Messaging bekommen und Veranstaltungen statt verwenden, und schließlich würde ich feststellen, dass es nicht der Grund war: -).

War es hilfreich?

Lösung

  

Erst wenn der Haupt-Thread seine Arbeit oder das Application.ProcessMessages Verfahren beendet genannt wird, tut GetMessage Rückkehr und mein Thread seine Arbeit beginnt zu tun.

Ich bezweifle, dass dies wirklich das, was passiert. AFAIK die beiden Nachrichtenschleifen sollten, so lange voneinander unabhängig sein, da Sie nicht andere Mittel zur Synchronisation des Threads nicht verwenden, wie Sendmessage () . Sind Sie sicher, dass der Faden in der Tat innerhalb von nicht blockiert GetMessage () und nicht innerhalb von Synchronisieren () (die mit Sendmessage () intern )?

  

Doing die Tests ich die WaitForSingleObject Funktion im Hauptthread verwendet, für ein paar Sekunden auf ein Ereignis warten.

Sie sollten nie verwenden WaitForSingleObject () im Hauptthread mit einem Timeout länger als 100 Millisekunden sagen, da dies Ihre GUI träge erscheinen wird. In der Tat würde ich raten Sie es nicht in den Haupt-Thread zu verwenden, da diese einfach Polling ist. Sende eine Nachricht von Ihrem Arbeitsthread statt.

Andere Tipps

Sie können eine Nachrichtenwarteschlange für Ihren Thread erstellen. Nur führen Sie den folgenden Code in Ihr Thema:

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

Der Aufruf von PeekMessage zwingt das Betriebssystem eine neue Nachrichtenwarteschlange für Ihren Thread zu erstellen. Sie müssen sicherstellen, dass dies zu synchronisieren, das heißt Sie müssen warten (beispielsweise über WaitForSingleObject) für den Anruf erfolgreich zu sein, bevor Sie Nachrichten auf diesen Thread (beispielsweise über Postthreadmessage) abgeben. Aus diesem Grund gibt es einen Aufruf an die SetEvent API in dem obigen Beispiel.

Edit:. Es tut uns das Beispiel in C zu sein, hoffen, dass für Sie in Ordnung,

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

Destillation Gewünscht, viele knorrigen Details in dem Weglassen der Teufel versteckt: die Haupt (oder VCL) Thread in Delphi besondere ist, weil viele Dinge unter der Haube sind nicht Thread-sicher, und es besitzt sie alle. Dinge wie die Nachrichtenschleife winden wegen Dinge warten, die mit dem VCL-Thread unter der Haube zu synchronisieren. Viele Menschen haben Theorien darüber. Die Sache, die die am besten zu funktionieren scheint, ist als Licht / reaktionsschnell wie möglich Ihren VCL-Thread halten wartet zu minimieren. Jeder ziemlich stimmt zu diesem Thema. Einige Leute haben Ideen über andere Dinge, die funktionieren könnte, aber andere Leute denken, sie sind nur Ärger bringen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top