Thread interruptibles - Besoin de conseils

Signaler
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
-
Messages postés
16
Date d'inscription
vendredi 13 décembre 2013
Statut
Membre
Dernière intervention
30 août 2014
-
Salut ta tou(te)s

J'ai une application dans laquelle je propose une TextBox de recherche.
Cette recherche est lancée dès que le contenu de la TB est modifié, afin de pouvoir proposer une liste d'Items.
Les données étant très nombreuses, la recherche complète dépasse les 3 ou 4 secondes et attendre 3 secondes à chaque lettre tapée n'est pas envisageable.

Je voudrais donc :
- lancer une recherche
- si la textbox est à nouveau modifiée, interrompre la précédente recherche afin d'en démarrer une autre

Je me suis orienté vers les Threads et j'ai trouvé des exemples avec les Threads interruptibles "Tasks", mais ceux-ci ne sont disponibles qu'à partir du Framework 4 et je suis obligé de rester avec mon Framework 2.

J'ai tenté de lancer ma tâche de recherche avec ça :
ThreadPool.QueueUserWorkItem(New WaitCallback( _
      AddressOf BuildSuggestedItemsList_xx))
+ un Booléen bAbort déclaré globalement que je bascule à True afin que la tâche en cours s'arrête (testée dans des If dans la tâche), mais la tâche lancée ne semble pas en tenir compte; je ne sais pas pourquoi.

Même pire :
Quand je vois qu'une précédente tâche est en cours, je mets mon bAbort à True puis j'attends dans une boucle
            Do While bSuggestedListInProgress
                Application.DoEvents()
            Loop
mais là, ça bloque la tâche précédemment lancée !
Je ne comprends pas pourquoi ...
Y a-t il une meilleure technique pour attendre ?

Vala
Jack [MVP VB]
NB : Je ne répondrai pas aux messages privés

11 réponses

Messages postés
378
Date d'inscription
samedi 22 septembre 2012
Statut
Membre
Dernière intervention
13 août 2017
14
Bonjour cs_Jack.

Comment s'effectue la recherche en elle-même ? Il faudrait peut-être d'abord accélérer l'algorithme de recherche.

Cordialement.
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
75
Merci Zermelo, mais cette recherche s'organise autour de 3 bases de données et près de 200.000 données.
De plus, je suis obligé de les traiter l'une après l'autre et dans un certain ordre, donc pas possible de faire 3 threads (1 pour chaque DB).
C'est donc normal et j'ai déjà peaufiné cette partie.

Je crois que je vais utiliser un BackgroundWorker qui est Cancellable, mais faut que je trouve une astuce pour avoir accès à mes RecordSets ainsi qu'à la ListView qui doit accueillir les résultats. Pas gagné ...

Salut cs_Jack,

L'histoire ne précise pas pourquoi tu n'utilises pas la propriété AutoCompleteCustomSource du TextBox ?
http://msdn.microsoft.com/fr-fr/library/system.windows.forms.textbox.autocompletecustomsource.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

Bon courage pour tes nouvelles fonctions sur ccm ;)
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
75
Salut Banana et merci pour tes encouragements ;-)

AutoCompleteCustomSource : c'est par là que j'avais commencé, mais cet outil ne permet de trouver que les "mots commençant par", alors que j'ai besoin d'une recherche partielle + l'ambition de mettre au point (plus tard) un algo genre Radcliff (mots proches de)

Et Linq ne donne pas de bon résultats non plus ?

Option Strict On
Public Class Form1
    Dim mesitems As New List(Of String) From {"navet", "banane", "citron", "barbot"}
    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        Dim requete As IEnumerable(Of String) = From valeur As String In mesitems Where valeur.Contains(TextBox1.Text)

        Debug.Print("-------")
        For Each element As String In requete
            Debug.Print(element)
        Next

    End Sub
End Class


--
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
75
Oups, voilà matière à travailler. Merci.
Sauf que mes items se trouvent dans des RecordSets et qu'il va falloir que j'approfondisse cette histoire de IEnumerable et voir comment faire le lien.

Hélas, je pars en déplacement ce soir et n'aurai pas l'occasion de replancher la question d'ici mardi.
Merci pour ces suggestions.
A+

Tu peux aussi étudier les "predicates" :
Option Strict On
Public Class Form1
    Dim mesitems As New List(Of String) From {"navet", "banane", "citron", "barbot"}

    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        Dim resultats As List(Of String) = mesitems.FindAll(AddressOf Cherche)
        Debug.Print("-------")
        For Each resultat As String In resultats
            Debug.Print(resultat)
        Next
    End Sub

    Private Function Cherche(ByVal item As String) As Boolean
        If item.Contains(TextBox1.Text) Then Return True
        Return False
    End Function

End Class
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
75
Je n'ai pas pu résister (pas tjrs facile en déplacement) à la mise en pratique de ces exemples.
Yearh !
Après la mise en pratique de la méthode 'predicate', la bufferisation (transformation des ADODB (de VB6) en Array de près de 180.000 données) + et la recherche (predicate) ne durent que 0.3 sec maxi !
Tout à fait acceptable.
Hyper supra cool !
Adieu les threads !

Un grand merci pour cette découverte.
(pitain fait chaud)
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
36
Salut,

Pour la variable booléenne, es-tu certain que la procédure lancée atteigne la lecture de la variable avant que la procédure suivante ne positionne le paramètre sur False ?

Pour ce qui est de DoEvents, que veux-tu dire par bloque la tâche ? Que la variable bAbort fonctionne et que la procédure se termine ? Si c'est le cas ça rejoint ce que j'ai dis plus haut.
Messages postés
14008
Date d'inscription
samedi 29 décembre 2001
Statut
Modérateur
Dernière intervention
28 août 2015
75
Merci Mayzz
Justement, c'était le problème majeur pour lequel je me posais la question :
Bien que ma variable bAbort soit déclarée en Public ET que ma longue procédure (que j'aimerai interrompre) ait des points de respiration (DoEvents), il semble que celle-ci, lancée par Thread, ne sache pas lire l'état de bAbort (cloisonnement ?).

Bref, "dis-moi ce qui te manque et je te dirai comment t'en passer" : Banana m'a envoyé sur une piste que je ne connaissais pas, les prédicates, et maintenant que j'ai testé (et compris) comment ça marche, j'en mets à toutes les sauces = Super efficacité = Plus besoin de Thread.
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
36
"Plus besoin de Thread." => En effet, comme je le dis plus bas je n'avais pas vu les réponses elles n'étaient pas affichées. Ou peut être que je n'ai pas fait attention à cause du nouveau site.
Messages postés
2814
Date d'inscription
mardi 15 avril 2003
Statut
Membre
Dernière intervention
2 juin 2020
36
Mince désolé pour la réponse. Il y a eu un bug et les réponses ne se sont pas chargées. N'ayant pas vu celles-ci j'ai répondu comme si de rien était...
Messages postés
16
Date d'inscription
vendredi 13 décembre 2013
Statut
Membre
Dernière intervention
30 août 2014

bonsoir,
peut-etre si c'est possible de avoir une 4 ieme table qui contient le resultat des 3 autres tables, qui est actualisé quand une des trois tables à des changements
simplement une idée
frederic