Comment appeler une fonction/procédure de manière asynchrone en Delphi (Sans composants)
Je suis en train d'exécuter une fonction ou de la procédure Delphi de façon asynchrone, mais sans l'aide d'un composant, est-il un moyen de le faire avec delphi fonctions de base?
Vous pouvez également exécuter votre procédure sur un fil. Utiliser ensuite le OnTerminate événement pour obtenir le résultat. Oui, dans ces jours de .NET et C# nous sont en quelque sorte des gâtés avec la facilité et la pratique de l'exécution des méthodes asynchronioulsly, mais c'est la façon dont il fonctionne sur Delphi.
J'ai une version de ce que je fais en c# jeje, maintenant que je suis en train de traduire en delphi (parce que je ne veux pas utiliser .NET) je vois ce que vous dites. Merci. J'ai finalement obtenu le travail avec un simple BeginThread seulement, je ne me soucie pas vraiment de savoir le résultat de la procédure, il suffit de faire quelque chose ou de Sortie. Merci pour votre msg.
Si vous vous demandez si la VCL a quelque chose comme BeginInvoke .NET out-of-the-box, alors la réponse est non. Cependant, vous pouvez obtenir quelque chose d'assez semblable dans la forme d'un petit appareil que vous reliez à votre programme, le AsyncCalls bibliothèque par Andreas Hausladen. Ce n'est pas un composant, donc je suppose qu'il qualifie. Il prend également en charge Delphi à partir de la version 5 et suivants. Très recommandé.
Edit:
Je vais ajouter un exemple puisque vous ne l'avez pas en cours d'exécution. Si vous obtenez le blocage dans votre code appelant, alors votre problème est l'absence de référence est conservé à la IAsyncCall pointeur d'interface que la fonction se termine. L'objet de la mise en œuvre de l'interface sera donc détruit immédiatement lorsque le renvoi temporaire est hors de portée. Le destructeur sera appelé dans le contexte de la VCL fil, et il va appeler WaitForSingleObject() ou une fonction similaire à attendre que le thread de travail à terminer. Le résultat de cela est que votre VCL thread se bloque.
Vous obtiendrez le comportement correct si vous maintenez une référence pour le pointeur d'interface:
De régler la minuterie pour être désactivé et la laisser en un très court Interval, par exemple, de 50 ms. Cliquez sur le bouton lance l'opération asynchrone:
Alors que l'opération est active aucune autre peut-être commencé. À la fin, il permet la minuterie pour informer la forme et de réinitialiser l'interface de référence:
Remarque comment il est même possible d'accéder au formulaire directement à partir de la méthode appelée, en utilisant EnterMainThread() et LeaveMainThread().
Code ci-dessus n'est pas le minimum absolu, elle est destinée à illustrer certaines idées.
J'ai vu que la bibliothèque hier, mais je voulais garder le code minimal, je pense que je vais finir par l'utiliser de toute façon. C'est un simple .pas d'unité de droit? Oui, il est, entre 2et 3 kLOC, il est donc assez minime déjà. Je ne pense pas que cela peut être battu. L'interface est extrêmement simple, tous les poils des choses est dans les implementation partie 😉 assurez-vous de garder IAsyncCall références jusqu'à ce que l'appel est terminé, sinon le dernier décompte de références décrémenter va bloquer. Il semble que ce sera la meilleure solution, je vous remercie beaucoup. J'ai essayé AsyncCall(@MyFunction, 0);, LocalAsyncCall(@Mafonction); et LocalAsyncVclCall(@MyFunction, 0); Mafonction a 20 secondes sleep() et se bloque à la fois la demande de ces 20 secondes, une idée de ce qui pourrait être mauvais? Je l'ai déjà évoqué cette possibilité dans mon commentaire, mais maintenant, j'ai ajouté un exemple pour que ce soit vraiment clair.
Vous pouvez également exécuter votre procédure sur un fil. Utiliser ensuite le OnTerminate événement pour obtenir le résultat. Oui, dans ces jours de .NET et C# nous sont en quelque sorte des gâtés avec la facilité et la pratique de l'exécution des méthodes asynchronioulsly, mais c'est la façon dont il fonctionne sur Delphi.
J'ai finalement obtenu le travail avec un simple BeginThread seulement, je ne me soucie pas vraiment de savoir le résultat de la procédure, il suffit de faire quelque chose ou de Sortie. Merci pour votre msg.
OriginalL'auteur Lobuno
Si vous vous demandez si la VCL a quelque chose comme BeginInvoke .NET out-of-the-box, alors la réponse est non. Cependant, vous pouvez obtenir quelque chose d'assez semblable dans la forme d'un petit appareil que vous reliez à votre programme, le AsyncCalls bibliothèque par Andreas Hausladen. Ce n'est pas un composant, donc je suppose qu'il qualifie. Il prend également en charge Delphi à partir de la version 5 et suivants. Très recommandé.
Edit:
Je vais ajouter un exemple puisque vous ne l'avez pas en cours d'exécution. Si vous obtenez le blocage dans votre code appelant, alors votre problème est l'absence de référence est conservé à la
IAsyncCall
pointeur d'interface que la fonction se termine. L'objet de la mise en œuvre de l'interface sera donc détruit immédiatement lorsque le renvoi temporaire est hors de portée. Le destructeur sera appelé dans le contexte de la VCL fil, et il va appelerWaitForSingleObject()
ou une fonction similaire à attendre que le thread de travail à terminer. Le résultat de cela est que votre VCL thread se bloque.Vous obtiendrez le comportement correct si vous maintenez une référence pour le pointeur d'interface:
De régler la minuterie pour être désactivé et la laisser en un très court
Interval
, par exemple, de 50 ms. Cliquez sur le bouton lance l'opération asynchrone:Alors que l'opération est active aucune autre peut-être commencé. À la fin, il permet la minuterie pour informer la forme et de réinitialiser l'interface de référence:
Remarque comment il est même possible d'accéder au formulaire directement à partir de la méthode appelée, en utilisant
EnterMainThread()
etLeaveMainThread()
.Code ci-dessus n'est pas le minimum absolu, elle est destinée à illustrer certaines idées.
Oui, il est, entre 2et 3 kLOC, il est donc assez minime déjà. Je ne pense pas que cela peut être battu. L'interface est extrêmement simple, tous les poils des choses est dans les
implementation
partie 😉 assurez-vous de garderIAsyncCall
références jusqu'à ce que l'appel est terminé, sinon le dernier décompte de références décrémenter va bloquer.Il semble que ce sera la meilleure solution, je vous remercie beaucoup.
J'ai essayé AsyncCall(@MyFunction, 0);, LocalAsyncCall(@Mafonction); et LocalAsyncVclCall(@MyFunction, 0); Mafonction a 20 secondes sleep() et se bloque à la fois la demande de ces 20 secondes, une idée de ce qui pourrait être mauvais?
Je l'ai déjà évoqué cette possibilité dans mon commentaire, mais maintenant, j'ai ajouté un exemple pour que ce soit vraiment clair.
OriginalL'auteur mghie