7
votes

Manière appropriée dans WPF MVVM de démarrer une tâche de recherche filetée

J'ai donc une tâche qui peut être préformée par mon interface graphique qui apportera des informations pour renseigner une vue de vue avec la réponse de la base de données SQL. suppose que je veux commencer cette tâche et garder mon interface libre de procéder à d'autres choses , et dans l'intervalle de jouer une animation "Recherche", Quelle est la bonne façon de le faire dans WPF / MVVM? Je suppose que vous devez démarrer un processus asynchrone et définir un BOOL attaché à un datrigrouting qui commence le storyboard d'animation. mais qu'est-ce que j'utilise pour démarrer le processus? Fil? Je suis toujours nouveau à WPF et je veux juste m'assurer que j'utilise les bonnes classes à moi.


0 commentaires

3 Réponses :


8
votes

J'utilise le thread de processus de fond pour faire des choses comme ça.

Voici un lien vers MSDN à ce sujet: http: // msdn.microsoft.com/en-us/library/system.componentmodel.backgroundorker.aspx

Détails supplémentaires liés à ceci.

Vous avez trois événements associés à votre Objet de processus de fond: Dowork, ReportProgress et OurkPompressé.

Maintenant, pour l'utiliser - et pour l'utiliser avec un observablecollection - vous voudrez informer l'objet de processus de base de pouvoir signaler des progrès (ceci est Une propriété booléenne que j'ai toujours définie explicitement, avec l'annulation de Permet).

Maintenant pour démarrer un processus, vous appellerez la méthode RunworkerAsync. Cette méthode a la possibilité d'accepter une variable d'objet au cas où vous auriez besoin de passer des données informatiques (si vous souhaitez plus d'une valeur, créez une structure à transmettre dans RunworkerAsync).

Le RunworkerAsync se déclenche de la Dowork Événement, alors le contrôle se dirige vers votre gestionnaire d'événements de Dowork. Voici le code (désinfecté) de l'endroit où je l'utilise: xxx

Qu'est-ce qui se passe ici, est que je reçois un jeu de données de ma couche de données, puis pendant que ce processus de fond n'est pas annulé, je marche dans la table de données, et lorsque je construis un nouveau dataObject, je signalons cet objet comme étant construit.

Maintenant, dans mon gestionnaire d'événements progresssif (la méthode de ProgReDReGress augmente la progressité événement) Le contrôle est de retour dans les mains du fil d'interface utilisateur afin que je puisse faire des choses comme un impact sur l'interface utilisateur et ajouter l'élément que je rapporte à une observablecollection.

Enfin, dans mon manutentionnaire d'événements complétés (dont l'événement correspondant est soulevé lorsque la méthode du gestionnaire d'événements dowork fonctionne à l'achèvement) Je vérifie que je vérifie si mes progrès ont été annulés (ce qui signifie parfois que je souhaite jeter l'observaCollection) et je peux avoir une incidence sur l'interface utilisateur (telle que supprimer une "recherche". Animation.


1 commentaires

Je faisais mal, je suis allé faire du fil, regardant cela aussi j'aime vraiment ça.



2
votes

Vous pouvez démarrer un nouveau fichier ou Backworker explicitement ou utilisez un threadpool . Je ne suis pas au courant d'une façon recommandée de le faire dans MVVM ...

Si votre fonctionnement asynchrone remplit une observation d'observation liée à un contrôle, notez que vous ne pouvez pas y ajouter d'éléments sur un fil différent. Vous devez le faire sur le fil du répartiteur du contrôle. Ou vous pouvez également utiliser Cette collection , qui soulève l'événement de collection sur le fil adéquat


2 commentaires

Je pense que j'ai un problème connexe ici à la collection observable, mon code est basé sur MVVM et que mon travailleur apporte donc des modifications au modèle de vue ... que le modèle est lié à des éléments de l'interface utilisateur ... Donc, il se bloque.


La liaison sur les propriétés scalaires fonctionne bien sur les threads, la notification de changement est automatiquement marquée sur le bon fil. Pour les collections, ce n'est pas pris en charge. Voir le lien que je vous ai donné pour une solution possible



1
votes
var t = new Thread((ThreadStart)delegate
{
    DoWork(...)
    Dispatcher.BeginInvoke((Action)delegate
    {
          SomethingOntheUiThread(...)
          FinishedWork(...);
    }
});

t.Start();

0 commentaires