2010-11-10 37 views
0

Je l'admets, j'apprends beaucoup de Stack Overflow.Comment utiliser les génériques pour créer une classe de threads qui renvoie des valeurs différentes

Après on this question J'ai compris comment créer une classe Thread découplée qui retourne un nombre entier. Je me demande maintenant comment le rendre plus générique.

Mais comment dois-je changer cela (où "entier" est codé en dur). J'utilise un très long nom de classe juste pour démonastrating fins:

type 
    TSyncMethod = Procedure(ThreadResult: integer) of Object; 
    TBackgroundThreadWithIntegerResult = class(TThread) 
    private 
    FResult: integer; 

à la contrepartie générique?

+1

Petite note: C'est un mauvais design. Pourquoi voudriez-vous créer une nouvelle classe de thread uniquement parce que le type de résultat de votre code de travail a changé? L'utilisation de 'TThread' est un détail d'implémentation ici, donc vous devriez choisir la composition plutôt que l'héritage. Créez une classe générique qui calcule le résultat, et permettez-lui de l'exécuter soit dans le thread appelant, soit dans un thread dédié, soit dans un thread d'un pool. – mghie

+0

Bien sûr, TBackGroundThreadWithIntegerResult n'est pas la meilleure solution, c'est pourquoi je pense utiliser des génériques. De cette manière, je n'ai pas besoin d'ajouter une sous-classe de TThread pour chaque type de résultat. Le fait est que les résultats sont toujours liés à une requête DB, parfois il peut retourner un entier, parfois une chaîne, parfois un TDataSet. Donc, ce que fait le thread est simplement d'exécuter une requête et d'enregistrer dans le résultat un entier, une chaîne ou un TDataSet. Quoi qu'il en soit comment assigner le résultat selon le type T générique ce n'est pas clair pour moi et c'est ce que j'ai demandé comme commentaire à la réponse de Jens Mühlenhoff. – LaBracca

+0

@mghie ok, mais comme je dois retourner une valeur générique, comment gérer la classe de calcul générique à l'intérieur du thread? – LaBracca

Répondre

3
type 
    TBackgroundThreadWithGenericResult<T> = class(TThread) 
    private 
    FResult: T; 
    public 
    type 
     TSyncMethod = Procedure(ThreadResult: T) of Object; 

Bien sûr, vous pouvez choisir un nom de type plus élaboré puis T pour votre type générique. J'ai mis le TSyncMethod dans la classe pour la simplicité. L'utilisation serait TBackgroundThreadWithGenericResult<Integer>.Create(...).

+0

ok merci. Je vois que cela fonctionne aussi si TsyncMethod est à l'intérieur de la classe. J'ai une question: comment gérer le type de résultat? Dans l'exemple non générique, c'était le résultat d'une requête: FResult: = FData.Query.Fields [0] .asinteger; ... comment cela se traduit-il dans la version générique? Je veux dire pour chaque comment puis-je définir le résultat d'une manière générique? – LaBracca

+0

@ user193655: C'est un peu plus compliqué, je n'utiliserais probablement pas de génériques dans ce cas et retournerai 'FData.Query.Fields [0] .Value' (en supposant que Query soit un descendant TDataSet) en tant que' Variant'. –

+0

Mais si je dois retourner un TDataset, cela ne sera pas possible avec les variantes. Une alternative est de renvoyer TDataSet seulement, donc dans le cas d'un entier j'extrais l'entier du champ. Quoi qu'il en soit, cela force à manipuler un ensemble de données même quand il aurait seulement besoin d'un entier. Pouvez-vous suggérer une autre approche? – LaBracca