2012-06-08 6 views
1

Référence à un objet (classe) à l'intérieur d'un fil échoueRéférence à un objet (classe) à l'intérieur d'un fil échoue

I ont un objet (« une classe vb ») qui doit être exécuté sur un fil séparé et communiquer avec les U/I.

Même en utilisant un exemple de code, l'objet ne peut pas être exécuté dans un thread. Je démontre ce problème avec deux exemples. Le premier appelle une fonction dans le formulaire et cela fonctionne parfaitement. La seconde crée un objet et effectue les mêmes appels, mais échoue.


exemple # 1 [contrat] (appelé dans un formulaire)

Private Delegate Sub FuctionToBeRunInThreadDelegate 

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 

    Console.WriteLine("Thread sample within FORM") 

    Dim Thread As New System.Threading.Thread(AddressOf FuctionToBeRunInThread) 
    Thread.Start() 

    Console.WriteLine("Thread sample within FORM completed") 

End Sub 

Public Sub FuctionToBeRunInThread() 

    If Me.InvokeRequired Then 
     Console.WriteLine("Inside new thread....") 
     Me.Invoke(New FuctionToBeRunInThreadDelegate(AddressOf FuctionToBeRunInThread)) 
    Else 
     Console.WriteLine("oFuctionToBeRunInThread") 
    End If 

    End Sub 

La sortie de la console lorsque la fonction est appelée dans une forme est la suivante:
échantillon de fil dans la forme
Échantillon de filetage dans le formulaire rempli
A l'intérieur du nouveau filetage ....
oFuctionToBeRunInThread

C'est ce que j'attendais. Le thread a démarré de manière asynchrone. Terminé très rapidement, et la fonction sait qu'il est dans un fil.




exemple # 2 [non-travail] (appel même fonction mais cette fois dans un objet)
Dans mon deuxième exemple, j'utilise un fichier externe contenant une classe et crée la enfiler de la même manière.

Voici la principale forme:

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click 

    Console.WriteLine("Thread sample using object started.") 

    Dim oEngine As New objTest() 
    Dim oThread As New System.Threading.Thread(AddressOf oEngine.oFuctionToBeRunInThread) 
    oThread.Start() 

    Console.WriteLine("Thread sample using object completed.") 


End Sub 


Voici le fichier externe contenant la définition de classe:

 
    Public Class objTest 

    Private Delegate Sub oFuctionToBeRunInThreadDelegate() 

    Public Sub oFuctionToBeRunInThread() 

     If frmInitial.InvokeRequired Then 
      Console.WriteLine("Inside new thread....") 
      frmInitial.Invoke(New oFuctionToBeRunInThreadDelegate(AddressOf oFuctionToBeRunInThread)) 
     Else 
      Console.WriteLine("oFuctionToBeRunInThread") 
     End If 

    End Sub 
    End Class 

Dans ce cas, la sortie est démontrant que la fonction ne fonctionne pas dans un fil. Il est comme suit:

Échantillon de fil en utilisant l'objet a commencé.
Échantillon de fil avec objet terminé.
oFuctionToBeRunInThread



RÉSUMÉ: Lorsque le thread crée l'objet, il apparaît que l'objet n'est pas réellement courir à l'intérieur d'un fil ou autre form.InvokeRequired serait vrai. J'ai d'autres exemples plus complexes où ceci est fortement vérifié et prouvé, mais j'ai fourni ces deux comme une démonstration très simple de mon problème.

Comment puis-je avoir un thread "propre" une série d'objets individuels de sorte que les objets sont exécutés de manière asynchrone et peuvent indépendamment rendre compte à l'U/I?

+0

duplication possible de e est une instance par défaut de la forme dans VB.Net mais pas dans C#, POURQUOI?] (http://stackoverflow.com/questions/4698538/there-is-a-default-instance-of-form-in-vb- net-but-not-in-c-why) –

+0

Vous êtes encore une autre victime du dernier paragraphe de la réponse à la question liée. –

+0

Hans, ce pourrait être un doublon ... peut-être à un œil ou une compréhension plus perspicace. Je ne suis pas capable de voir comment ils sont identiques. Merci pour le lien cependant. – NameIsPete

Répondre

1

après le débogage de votre code, il semble que frmInitial.InvokeRequired ne s'exécute pas correctement.

============================================== =========

suis donc à nouveau (avec une solution bien sûr):

Public Class frmInitial 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     Console.WriteLine("event started") 

     Dim obj As New ObjTest() 
     Dim threadobj As New System.Threading.Thread(AddressOf obj.dosomework) 
     threadobj.Name = "debugme" 

     'passing the current form reference to the thread function 
     threadobj.Start(Me) 

     Console.WriteLine("event completed") 
    End Sub 
End Class 

screen snapshot

Public Class ObjTest 
     Private Delegate Sub dosomeworkDelegate(ByVal f As Form) 

     Public Sub dosomework(ByVal f As Form) 
      ' Check if the form can be accessed from the current thread. 
      If Not f.InvokeRequired Then 
       ' Access the form directly. 
       Console.WriteLine("delegate executed") 
       f.Controls("textbox1").Text = "thread invoked successfuly" 
      Else 
       ' Marshal to the thread that owns the form. 
       Dim del As dosomeworkDelegate = AddressOf dosomework 
       Dim param As Object() = {f} 
       Console.WriteLine("executing delegate") 
       f.BeginInvoke(del, param) 
      End If 
     End Sub 

End Class 

me croire son chemin mieux que d'étudier pour mon numérique examen d'analyse :-)

+0

C'est vrai. Lorsque la fonction est un membre du formulaire "Me.InvokeRequired" renvoie True. Toutefois, dans le cas où la fonction est membre d'une classe, "frmInitial.InvokeRequired" renvoie false. Une idée pourquoi tout cela est-il? Je suis vraiment perplexe. Merci d'avoir pris le temps de regarder cela. – NameIsPete

+0

Génial! Je vous remercie! Je vais essayer ça demain. Cela a beaucoup de sens. – NameIsPete

+0

** Merci ** - Cela fonctionne. Je suis encore un peu confus au sujet du filetage global, mais je crois que je peux plier cela dans le projet. Merci beaucoup! – NameIsPete

Questions connexes