2017-02-21 1 views
-1

Avant de commencer, je sais que vous avez déjà un tas de réponses à cette question, mais laissez-moi vous expliquer ce qui se passe. Je veux fondamentalement ajouter des textes à un élément RichTextBox, cela me sert comme un logger pour informer l'utilisateur de chaque action d'un traitement de fichier, mais le texte est ajouté à la RichTextBox via une boucle for, et si j'exécute cette boucle dans la même classe "Form1.vb" l'interface utilisateur gèle jusqu'à la fin de la boucle.Comment définir le texte à l'élément créé dans un autre thread

J'ai décidé d'exécuter la boucle dans un thread séparé pour éviter le gel de l'interface utilisateur, et c'est là que mon problème commence.

Form1.vb

Imports System.Threading 


Public Class Form1 

    Dim myThread As Thread 

    Private Sub appendMyText() 
     ' Cross-thread operation not valid: Control txtLogger accessed from a thread other than the thread it was created on. 
     txtLogger.AppendText("Hello World" & vbNewLine) 
    End Sub 

    Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click 
     myThread = New Thread(New ThreadStart(AddressOf appendMyText)) 
     myThread.Start() 
    End Sub 

End Class 

Je ne peux pas accéder à l'élément txtLogger d'un autre fil, alors j'ai essayé l'exemple MSDN https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

Il me montre comment accéder à l'élément effectuer des appels à thread sécurisé, en utilisant un délégué.

donc mon code est édité

Form1.vb

Imports System.Threading 

Public Class Form1 

    Dim myThread As Thread 
    Delegate Sub AppendMyText(ByVal text As String) 

    ' Add the text to RichTextBox 
    Private Sub addText(ByVal txt As String) 
     If txtLogger.InvokeRequired Then 
      Dim myDelegate = New AppendMyText(AddressOf addText) 
      Me.Invoke(myDelegate, {txt}) 
     Else 
      txtLogger.AppendText(txt) 
     End If 
    End Sub 

    ' Call the method that add text to RichTextBox 
    Private Sub threadSafe() 
     Me.addText("Hello World" & vbNewLine) 
    End Sub 

    Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click 
     myThread = New Thread(New ThreadStart(AddressOf threadSafe)) 
     myThread.Start() 
    End Sub 

End Class 

Le code fonctionne vraiment cette façon, le texte est joint en annexe à RichTextBox, mais le tout le code est dans la même classe Form1.vb

Dans mon projet d'origine, la boucle for est exécutée dans une autre classe, je vais la nommer "Class1.vb" ici.

C'est l'exemple de code

Class1.vb

Public Class Class1 

    Public Sub count() 
     Dim i As Integer 

     For i = 0 To 100 
      ' this method will be executed by thread "myThread" 
      ' how to append text to txtLogger from here? 
      Debug.WriteLine("Index: {0}", i) 
     Next 
    End Sub 

End Class 
+0

Vous pouvez transmettre la forme en tant que paramètre à la méthode 'count'. –

+0

J'ai déjà essayé de cette façon. Mais accéder directement aux éléments d'un autre thread n'est pas recommandé, et je sais pourquoi! Mon projet doit ajouter du texte plus de 200 fois, et l'application s'arrête de répondre et se bloque lorsque je passe le formulaire en paramètre, car le formulaire s'exécute sur son propre thread. –

+0

L'accès à une méthode personnalisée via le formulaire doit toujours être possible tant que cette méthode appelle l'accès aux éléments de l'interface utilisateur. –

Répondre

2

passer le formulaire référence à la classe

Dans votre formulaire

Dim MyClass as Class1 
MyClass = New Class1(Me) 

En vous r classe

Public Class Class1 

    Private Parent_From as Form1 
    Public Sub New(Parent as Form1) 
      Parent_From = Form 
    End sub 
    Public Sub count() 
     Dim i As Integer 
     For i = 0 To 100 
      ' this method will be executed by thread "myThread" 
      Parent_Form.addTExt("Whatever") 
      Debug.WriteLine("Index: {0}", i) 
     Next 
    End Sub 
End CLass 
+1

Great! Ça a marché! J'ai déjà essayé de passer le formulaire en paramètre, mais en oubliant d'appeler la même méthode pour ajouter le texte, au lieu que j'accédais à l'élément en utilisant Parent_From.txtLogger.AppendText ("quelque chose") .. Merci beaucoup! –