Je suis nouveau à multithreading, mais pas un novice complet. J'ai besoin d'effectuer un appel à un service Web dans un thread de travailleur.
dans le fil principal, j'ai une forme (Tform) avec un membre de données privé (chaîne privée) que seul le fil du travailleur écrira (je passe le pointeur sur le fil avant qu'il ne reprenne). Lorsque le fil du travailleur a terminé son appel de service Web et écrit la réponse résultante XML au membre privé sur le formulaire, le thread du travailleur utilise PostMessage pour envoyer un message à la poignée du formulaire (que j'ai également transmis dans le fil avant de reprendre). < / p> Cela fonctionne bien, mais maintenant je veux faire la même chose edit strud> p> Ce que je veux vraiment, c'est le code (si possible) Permettez-moi de remplacer la ligne p> avec p>
3 Réponses :
J'ai utilisé cette technique avant de réussir: Envoyer des messages à des messages non Applications fenêtres P>
Fondamentalement, utilisez un deuxième thread en tant que pompe à message sur une poignée obtenue via AllateHwnd. Ceci est certes irritant et vous feriez mieux d'utiliser une bibliothèque pour gérer tous les détails. Je préfère omnithreadlibrary mais il y en a d'autres - voir Comment choisir entre les différentes façons de faire de la filetage dans Delphi? et < Un href = "https://stackoverflow.com/questions/670641/delphi-threading-frameworks"> Delphi - Frameformes de filetage . P>
+1 pour ne pas réinventer la roue. Regarde omnithreadlibrary.
Allocathwnd a fait le travail. Merci Moz.
Vous pouvez allouer votre propre poignée avec AllocHWND et utiliser cela comme une cible postmessage.
TTestThread = class(TThread) private FSignalShutdown: boolean; // hidden window handle FWinHandle: HWND; protected procedure Execute; override; // our window procedure procedure WndProc(var msg: TMessage); public constructor Create; destructor Destroy; override; procedure PrintMsg; end; constructor TTestThread.Create; begin FSignalShutdown := False; // create the hidden window, store it's // handle and change the default window // procedure provided by Windows with our // window procedure FWinHandle := AllocateHWND(WndProc); inherited Create(False); end; destructor TTestThread.Destroy; begin // destroy the hidden window and free up memory DeallocateHWnd(FWinHandle); inherited; end; procedure TTestThread.WndProc(var msg: TMessage); begin if Msg.Msg = WM_SHUTDOWN_THREADS then // if the message id is WM_SHUTDOWN_THREADS // do our own processing FSignalShutdown := True else // for all other messages call // the default window procedure Msg.Result := DefWindowProc(FWinHandle, Msg.Msg, Msg.wParam, Msg.lParam); end;
Que Allocathwnd n'est pas un fil de sécurité est une source de beaucoup d'irritation. Il semble que Embarcadero ne change pas leur politique. J'utilise mon propre code d'accrochage noddy pour remplacer Allochwnd au moment de l'exécution avec une version protégée par une section critique.
@David: D'accord, mais il y a des choses dans leur code qui sont beaucoup plus irritantes et qui ne sont toujours pas réparées :) Je serais heureux si cela ne serait que Allocathwnd.
Tant que le nouveau thread est créé par le fil de l'interface graphique, il n'y a aucun problème avec ce code. Le constructeur fonctionne dans le contexte du fil qui l'appelle.
Alternatives basées sur l'utilisation d'un événement:
Utilisez à l'onduleur du fil (déjà présent ) En combinaison avec un drapeau: p>
TMyDataModule = class(TDataModule) private procedure OnWebServiceCallComplete(Sender: TObject); ... TMyThread = class(TThread) public property TerminateFlag: Integer ... ... procedure TMyDataModule.StartWorkerThread; ... MyWorkerThread.OnTerminate := <Self.>OnWebServiceCallComplete; ... procedure TMyDataModule.OnWebServiceCallComplete(Sender: TObject); begin if MyWorkerThread.TerminateFlag = WEBCALL_COMPLETE then ... end;
Ajoutez une nouvelle propriété d'événement à la classe de thread dans laquelle vous pouvez fournir le drapeau sous forme de paramètre pour indiquer le résultat de terminaison / thread. Quelque chose comme montré ici . Assurez-vous de synchroniser l'appel de l'événement. Ou oubliez le paramètre et appelez simplement l'événement si l'exécution est terminée de manière gracieuse (comme si vous le faisez maintenant). P> LI> ol> p>
J'apprécie vraiment cette alternative. Il semble plus élégant. Je vais l'essayer.
À la deuxième pensée, l'utilisation de messages est mon modèle préféré. Merci quand même.