11
votes

Comment gérer la valeur de retour d'un fil?

J'ai créé une classe dérivée de tthread qui s'exécute en arrière-plan une requête.

Je veux que cette classe soit découplée du client.

Ce type de fil a Le but d'exécuter une vérification simple (comme le nombre d'utilisateurs sont actuellement connectés à l'application, sans bloquer l'interface utilisateur), une idée simple est donc d'utiliser la méthode de synchronisation.

De toute façon puisque je veux que ce soit découplé je passe dans le constructeur un paramètre de type xxx

tyncmethod est une méthode sur le client (un formulaire dans mon cas).

Quoi qu'il en soit, comment puis-je passer la valeur à TsyncMethod? Je devrais écrire le résultat sur une "place globale" puis à l'intérieur de mon Tsyncmethod je vérifie-moi?

J'ai également essayé de penser à xxx

mais Bien sûr, lorsque j'appelle synchroniser (mysyncmethod) je ne peux pas passer des paramètres à celui-ci.


0 commentaires

5 Réponses :


3
votes

Quelle version de DELPHI utilisez-vous? Si vous êtes sur D2009 ou plus récent, vous pouvez transmettre une méthode anonyme sur synchroniser qui ne prend aucun paramètre mais fait référence à des variables locales, les transmettant "sous le radar" dans le cadre de la fermeture.


1 commentaires

Ok, je viens de rechercher des méthodes anonymes après votre réponse. Pourriez-vous s'il vous plaît expliquer que tu veux dire quoi? Si je passe une méthode anonyme Comment puis-je appeler la méthode de ma cliente TsyncMethod. Si j'appelle Synchroniser (la procédure commence quelque chose; fin) Comment utiliser TsyncMethod. S'il vous plaît comprendre que je suis nouveau aux méthodes anonymes. (J'utilise D2009).



3
votes

Vous pouvez essayer mon composant TCommThread. Il vous permet de transmettre des données sur le fil principal sans vous soucier de l'une des complexités de threads ou de messages Windows.

Voici le code si vous souhaitez l'essayer. Vous pouvez également voir un exemple de code Ici . P>

bibliothèque de commTHead: p> xxx pré>

Pour utiliser la bibliothèque, descendez simplement votre fil du TCOMMTHADAD Fil et remplacement de la procédure d'exécution: p> xxx pré>

Suivant, créez un descendant du composant TstatusCommThreadDispatch et définissez ses événements. P>

procedure THostDiscovery.DoOnReceiveThreadMessage(Sender: TObject;
  MessageId: Integer; CommThreadParams: TCommThreadParams);
begin
  inherited;

  case MessageId of

    CTID_MY_MESSAGE_ID:
      begin
        // Process the CTID_MY_MESSAGE_ID message
        DoSomethingWithTheMessage(CommThreadParams.GetParam('MyThreadOutputParameter'),
                                  CommThreadParams.GeObject('MyThreadObject'));
      end;
  end;
end;


0 commentaires

4
votes

en utilisant omnithreadlibrary : xxx

Création de l'objet de la tomnifuture démarre automatiquement l'arrière-plan Fil exécutant votre code. Plus tard, vous pouvez attendre sur le résultat en appelant .Value ou vous pouvez utiliser .Valuer ou .isdone à vérifier si le thread a déjà terminé ses travaux.


2 commentaires

Bonne idée. Comme ma réponse, cela nécessitera également D2009 ou plus tard.


Merci, je garderai le lien dans mes favoris.



6
votes

Pour un exemple aussi simple, vous pouvez placer la valeur souhaitée dans un champ de membre du fil (ou même dans la propriété de retour du fichier de la propriété ), puis synchroniser () l'exécution du rappel en utilisant un Méthode de filetage intermédiaire, où vous pouvez ensuite transmettre la valeur au rappel. Par exemple: xxx


1 commentaires

Cela répond exactement à ma question: la méthode de thread intermédiaire était la liaison manquante. Quoi qu'il en soit, merci beaucoup à tous pour les réponses vraiment intéressantes, je les évite tous.



1
votes

Créez un formulaire et ajoutez une liste de liste, deux boutons et modifiez votre formulaire. Ensuite, utilisez ce code:

unit Unit1;

    interface

    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

    type
      TSyncMethod = procedure(ReturnValue: integer) of object;
      TMyThread = class(TThread)
       private
          fLowerLimit: Integer;
          fUpperLimit: Integer;
          FMethod: TSyncMethod;
          FMethodValue: Integer;
          procedure UpdateMainThread;
       protected
          procedure Execute; override;
       public
          constructor Create(AMethod: TSyncMethod;lValue, uValue: Integer; Suspended: Boolean);
       end;



      TForm1 = class(TForm)
        Button1: TButton;
        Edit1: TEdit;
        Button2: TButton;
        ListBox1: TListBox;
        procedure Button2Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
         MyMethod: TSyncMethod;
         ReturnValue : Integer;
         CountingThread: TMyThread;
         procedure MyTest(X : Integer);
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    constructor TMyThread.Create(AMethod: TSyncMethod;lValue, uValue: Integer; Suspended: Boolean);
    begin
       FMethod := AMethod;
       Inherited Create(Suspended);
       fLowerLimit := lValue;
       fUpperLimit := uValue;
       FreeOnTerminate := True;
       Priority := tpLowest;
    end;

    procedure TMyThread.Execute;
    var
       I: Integer;
    begin

       For I := fLowerLimit to fUpperLimit do
          if (I mod 10) = 0 then
             Synchronize(UpdateMainThread);

      FMethod(FMethodValue);
    end;

    procedure TMyThread.UpdateMainThread;
    begin
       Form1.ListBox1.Items.Add('Hello World');
       FMethodValue :=  Form1.ListBox1.Count;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
       MyMethod := MyTest;
       CountingThread := TMyThread.Create(MyMethod,22, 999, True);
       CountingThread.Resume;
    //   ShowMessage(IntToStr(ReturnValue));
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
      ShowMessage(Edit1.Text);
    end;

    procedure TForm1.MyTest(X: Integer);
    begin
      ShowMessage(IntToStr(X));
    end;

    end.        


0 commentaires