2010-09-04 5 views
0

J'ai un thread s'exécutant sur un formulaire enfant, je veux activer un contrôle sur le formulaire parent mais je ne peux pas. Cela fonctionne très bien si elle est fait à partir de l'enfant forme thread d'interface utilisateur:Accès aux contrôles entre les formulaires

(FormMain.SetControlPropertyValue (FormMain.RBSQL2005, "Vérifié", true))

mais pas d'un fil conducteur sur le formulaire enfant:

Public Class FormRestoreDB 
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    Dim t = New Thread(AddressOf UpdateListView1) 
    t.Start() 
End Sub 


Private Sub UpdateListView1() 
    'FormMain.SetControlPropertyValue(FormMain.RBSQL2005, "Checked", True) 
    FormMain.RBSQL2005.Checked = True 
End Sub 

End Class 


Public Class FormMain 

Delegate Sub SetControlValueCallback(ByVal oControl As Control, ByVal propName As String, ByVal propValue As Object) 

Public Sub SetControlPropertyValue(ByVal oControl As Control, ByVal propName As String, ByVal propValue As Object) 
    If (oControl.InvokeRequired) Then 

     Dim d As New SetControlValueCallback(AddressOf SetControlPropertyValue) 
     oControl.Invoke(d, New Object() {oControl, propName, propValue}) 
    Else 
     Dim t As Type = oControl.[GetType]() 
     Dim props As PropertyInfo() = t.GetProperties() 
     For Each p As PropertyInfo In props 
      If p.Name.ToUpper() = propName.ToUpper() Then 
       p.SetValue(oControl, propValue, Nothing) 
      End If 
     Next 
    End If 
End Sub 

End Class 

Qu'est-ce que je fais mal?

alt text

Répondre

3
FormMain.SetControlPropertyValue(FormMain.RBSQL2005, "Checked", True) 

C'est l'une des horreurs induites par le soutien de VB.NET pour utiliser le nom du type d'une forme de se référer à l'exemple de la forme. C'est un anachronisme reporté de VB6 où l'utilisation du nom de type d'un formulaire était normale.

Cela tombe en morceaux lorsque vous utilisez des threads car "FormMain" a une affinité de thread. En d'autres termes, il a l'attribut <ThreadStatic>. Lorsque vous l'utilisez dans un thread de travail, vous obtenez une instance nouvelle du formulaire, pas celle que l'utilisateur regarde. Cette nouvelle instance n'est pas visible car sa méthode Show() n'a jamais été appelée. C'est pourquoi vous ne voyez pas votre code avoir d'effet. Si vous appelez Show() dans votre code, vous le verrez apparaître. Il est cependant tout à fait mort, le fil ne pompe pas une boucle de message. Un autre effet que vous auriez dû remarquer était que InvokeRequired est False, vous savez que cela ne peut pas être correct.

Vous devrez arrêter d'utiliser FormMain. Si ce code vit à l'intérieur de cette classe, vous pouvez simplement utiliser Moi. Si ce n'est pas le cas, vous devrez passer la référence du formulaire avec une propriété ou un argument constructeur. Le correctif Q & D est d'utiliser Application.OpenForms (0)

+0

Merci Hans, ça a du sens. Pourriez-vous me montrer un exemple? Dites comment changer \ mettre à jour un contrôle sur un formulaire parent à partir d'un thread s'exécutant sur l'enfant? – madlan

+1

Ne le faites pas. Soulevez un événement, comme le font tous les contrôles Windows Forms lorsque quelque chose se produit. Le formulaire parent peut s'y abonner et mettre à jour son (ses) contrôle (s). –

Questions connexes