7
votes

Comment est-ce que je "faiseurs" dans WPF?

J'ai lu que la version C # est la suivante:

Application.Current.Dispatcher.Invoke(
  DispatcherPriority.Background,
  New Action(Sub()

             End Sub))


7 commentaires

DOEVENTS? Je crois qu'ils avaient l'habitude de faire des coups de retour dans VB6, avant que les personnes ne réalisaient qu'une application pourrait avoir plus que le fil de l'interface utilisateur.


Eh bien, la convention moderne consiste à utiliser le thread.sleep (1) ou similaire, mais cela ne fonctionne pas lorsque vous devez sortir temporairement d'un fil pour permettre à l'interface utilisateur de se mettre à jour et de rester au milieu d'une boucle de traitement dans WPF .


@SLC: Si vous faites votre traitement dans un autre thread, vous n'avez pas besoin de dire à l'interface utilisateur de se mettre à jour (en une seule voie d'actualisation générale).


Vous devez interrompre le fil de l'interface utilisateur pour l'informer pour mettre à jour une barre de progression, ce qui est possible sous Windows Formulaires à l'aide de la méthode Invoke, mais je pense que c'est différent dans WPF, c'est pourquoi cette méthode est utilisée ... mais je ne sais honnêtement rien de wpf et je suis juste convertir c # à vb.


J'ai ceci dans mon application au même endroit. Le problème est que thread.sleep (1) et thread.join () bloquez également la file d'attente du répartiteur. Dans mon application, j'ai un deuxième fil où beaucoup de travaux sont terminés. Au cours de l'événement d'application-sortie, je fermeture qui enfilait et attendez jusqu'à ce qu'il finit. Cependant, comme ce fil touche également certains des objets d'interface utilisateur, la file d'attente du répartiteur doit rester en vie. Ainsi, des doigts sont nécessaires.


@WILL Ce n'est pas comme s'il n'y avait jamais une utilisation pour elle ( Bea.stollnitz.com/blog/? p = 59 )


Est-ce que cela répond à votre question? Où est l'application.Deevents () dans WPF?


5 Réponses :


0
votes

Utilisez le mot-clé de fonction:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, New Action(Function() Do ... End Function))


2 commentaires

Le problème est que l'action ne fait rien, alors que puis-je mettre là-bas qui n'est "rien"? De plus, une fonction renvoie une variable.


Compilez-vous si vous supprimez simplement les points? Quelle version de vb / .net parle-t-on ici?



6
votes

vb.net prend en charge les délégués anonymes, mais uniquement comme fonction de déclaration unique. (Fonctions multi-instructions anonymes et anonyme SUB S ont été ajoutés à VB10 in .NET 4)

Pour fournir le contexte, DOEVENTS a été conçu pour permettre un seul filetage. Environnement Pour mettre à jour l'interface utilisateur et traiter d'autres messages Windows pendant que des travaux ont été effectués. Il ne devrait y avoir aucun avantage à appeler doevents (ou, comme vous le faites ici, ce faisant si indirectement en exécutant une fonction "null" sur le répartiteur) à partir d'un autre fil, car le thread de l'interface utilisateur doit être mis à jour. par lui-même.

Dans l'intérêt de répondre à votre question, l'option la plus simple serait une chose comme celle-ci: xxx

mais, encore une fois, je peux 't voir ce que cela accomplirait réellement.

Si ce que vous cherchez, c'est simplement comment exécuter du code sur le thread de l'interface utilisateur (comme le contrôler.invoke de formulaires Windows) , alors Dispatcher.invoke (ce que vous utilisez) est correct, vous devrez simplement traduire vos méthodes anonymes en ligne en fonctions discrètes et transmettre ceux-ci en tant que délégués. Il peut y avoir des gens que vous pouvez vous échapper avec des personnes anonymes. Par exemple, si tout ce que vous faites est de mettre à jour une barre de progression, vous pouvez faire: xxx

Ceci fonctionne car toutes les affectations renvoient la valeur stockée à gauche de la gauche de la tâche. Vous ne pouvez toutefois pas simplement appeler un sous-genre (ce qui suit ne compilera pas à moins que CertainfonctionnementName renvoie une valeur): xxx

dans d'autres mots, aucun des délégués anonymes qui figurent dans le code C # que:

  • sont plus d'une déclaration
  • Ne retourne pas de valeur (ce qui signifie qu'il s'agit d'un seul appel à une méthode, pas une fonction)

    alors vous devrez créer des fonctions pour les personnes et transmettre des délégués à ces fonctions plutôt que d'intensifier le code que vous avez dans C #.


5 commentaires

L'interface utilisateur ne peut se mettre à jour que si cela a la chance de savoir cependant, qui est à la fin d'une fonction. C'est pourquoi votre application devient insensible si vous y mettez une boucle dans celle-ci, et même avec un sommeil à filetage ne mettra pas à jour les composants de l'interface utilisateur dans une boucle sans faire d'invoquer des formulaires Windows pour forcer un commutateur à l'autre fil. Je spécule c'est la même chose.


Vous pouvez modifier la fonction () sur Sub () et simplement avoir un sous vide () tel que j'ai spéculé dans mon édition, car je viens de le confirmer en code et qu'il semble fonctionner.


@SLC: Ceci n'est vrai que si ce que vous faites est en tenant sur le fil de l'interface utilisateur . Si le code est exécuté sur un autre fil, cela n'est pas nécessaire. Si ce que vous faites est exécutant sur le fil de l'interface utilisateur et qu'il prend suffisamment de temps pour nécessiter une mise à jour de l'interface utilisateur explicite, elle doit alors être déplacée vers un autre fil.


@SLC: l'option sous fonctionne uniquement dans VB10 (VisualStudio 2010 / .NET 4).


Robinson - Les opérations en mouvement vers un autre fil ne sont pas toujours praticables. Dans les cas où vous chargez un flowdocument d'un formulaire XAML sérialisé, par exemple, vous ne pouvez pas le produire sur le thread de BG, puis l'afficher sur le fil de l'interface utilisateur. Il doit être créé et chargé sur le fil de l'interface utilisateur.



1
votes

Vous avez deux questions ici, alors je vais ajouter deux réponses. Ici, je réponds "Comment faire des doigts dans WPF". Bea Stollnitz couvre ceci sur son blog , et voici le code dans VB:

publicShared Sub WaitForPriority(priority As DispatcherPriority)
    Dim frame As New DispatcherFrame()
    Dim dispatcherOperation As DispatcherOperation = Dispatcher.CurrentDispatcher.BeginInvoke(priority, New DispatcherOperationCallback(ExitFrameOperation), frame)
    Dispatcher.PushFrame(frame)
    If dispatcherOperation.Status <> DispatcherOperationStatus.Completed Then
        dispatcherOperation.Abort()
    End If
End Sub

Private Shared Function ExitFrameOperation(obj As Object) As Object
    (DirectCast(obj, DispatcherFrame)).[Continue] = False
    Return Nothing
End Function


0 commentaires

4
votes

Vous pouvez simplement appeler cette méthode si vous voulez que quelque chose soit actualisé sur l'interface utilisateur:

System.Windows.Forms.Application.DoEvents


0 commentaires

1
votes

ou simplement utiliser un répartiteur pour vous faire des doigts () pour WPF:

    'The WPF equivalent of DoEvents!!
Public Sub DoEvents()
    Dispatcher.Invoke(New Action(Function()
                                     Return Nothing
                                 End Function), DispatcherPriority.ContextIdle, Nothing)
End Sub


0 commentaires