2009-12-02 5 views

Répondre

4

Vous pouvez également exécuter votre procédure sur un thread. Utilisez ensuite l'événement OnTerminate pour obtenir le résultat. Oui, en ces jours de .NET et C# nous sommes une sorte de gâté avec la forme facile et pratique de l'exécution des méthodes asynchronioulsly, mais c'est la façon dont cela fonctionne sur Delphi.

+0

J'ai une version de ce que je fais dans C# jeje, maintenant que j'essaie de traduire en Delphi (parce que je ne veux pas utiliser .NET), je vois ce que vous dites. Merci. – Sebastian

+0

Je l'ai finalement fait fonctionner avec un simple BeginThread, je ne me soucie pas vraiment du résultat de la procédure, il suffit de faire quelque chose ou de sortir. Merci pour votre message. – Sebastian

16

Si vous demandez si la VCL a quelque chose de prêt à l'emploi like BeginInvoke in .NET, alors la réponse est non. Cependant, vous pouvez obtenir quelque chose de très similaire sous la forme d'une petite unité que vous liez à votre programme, la bibliothèque AsyncCalls par Andreas Hausladen. Ce n'est pas une composante, donc je suppose que cela se qualifie. Il prend également en charge Delphi à partir de la version 5. Très recommandé

Edit:

Je vais ajouter un exemple puisque vous ne l'avez pas en cours d'exécution. Si vous obtenez un blocage dans votre code d'appel, votre problème est qu'aucune référence n'est conservée au pointeur d'interface IAsyncCall renvoyé par la fonction. L'objet implémentant l'interface sera donc détruit immédiatement lorsque la référence temporaire sortira de sa portée. Le destructeur sera appelé dans le contexte du thread VCL, et il appellera WaitForSingleObject() ou une fonction similaire pour attendre la fin du thread de travail. Le résultat de cela est que votre thread VCL bloque.

Vous obtiendrez le comportement correct si vous maintenez une référence au pointeur d'interface:

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Timer1: TTimer; 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure Button1Click(Sender: TObject); 
    procedure Timer1Timer(Sender: TObject); 
    private 
    fAsyncCall: IAsyncCall; 
    procedure WaitForIt(ADelay: integer); 
    end; 

Réglez la minuterie est désactivé et laissez-il un très court Interval, disons 50 ms. Le clic sur le bouton lance l'opération asynchrone:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Button1.Enabled := FALSE; 
    fAsyncCall := AsyncCall(WaitForIt, 1000); 
end; 

procedure TForm1.WaitForIt(ADelay: integer); 
begin 
    Sleep(ADelay); 

    EnterMainThread; 
    try 
    Randomize; 
    Color := RGB(Random(256), Random(256), Random(256)); 
    Timer1.Enabled := TRUE; 
    finally 
    LeaveMainThread; 
    end; 
end; 

Lorsque l'opération est active, aucune autre opération ne peut être lancée. A la fin, il permet la minuterie de notifier le formulaire et réinitialiser la référence de l'interface:

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    Timer1.Enabled := FALSE; 
    Assert((fAsyncCall <> nil) and fAsyncCall.Finished); 
    fAsyncCall := nil; 
    Button1.Enabled := TRUE; 
end; 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
    CanClose := (fAsyncCall = nil) or fAsyncCall.Finished; 
end; 

Notez comment il est même possible d'accéder au formulaire directement à partir de la méthode appelée, en utilisant EnterMainThread() et LeaveMainThread().

Au-dessus du code n'est pas le minimum absolu, il est destiné à démontrer quelques idées seulement.

+0

J'ai vu cette bibliothèque hier, mais je voulais garder le code minimal, je pense que je vais finir par l'utiliser quand même. C'est une simple unité .pas, n'est-ce pas? – Sebastian

+0

Oui c'est, seulement entre 2 et 3 kLOC, donc c'est déjà assez minime. Je ne pense pas que cela puisse être battu. L'interface est extrêmement simple, tous les trucs poilus sont dans la partie 'implementation' ;-) Assurez-vous juste de garder les références' IAsyncCall' jusqu'à ce que l'appel soit terminé, sinon le dernier décompte du nombre de références bloquera. – mghie

+0

On dirait que ce sera la meilleure solution, merci beaucoup. – Sebastian

Questions connexes