2009-02-11 6 views
1

Si je définis la propriété Text d'un formulaire à partir d'un thread non-UI, j'ai besoin d'utiliser Invoke pour éviter une erreur d'inter-thread. Mais, je peux lire la propriété Text sans utiliser Invoke. Est-ce sûr? Si j'essaie de lire la propriété Handle d'un formulaire, j'obtiens une erreur d'inter-threading. Si je lis la propriété IsDisposed d'un formulaire cela fonctionne très bien. Comment puis-je savoir quand j'ai besoin d'utiliser Invoke? Dois-je utiliser toujours pour appeler et écrire des valeurs de propriété?Comment savoir si Invoke est requis pour une propriété?

Répondre

4

Chaque fois que vous êtes dans un thread autre que le thread d'interface utilisateur, vous devez utiliser Invoke lors de l'accès aux objets de l'interface utilisateur. Utilisez la propriété InvokeRequired pour savoir si vous êtes en fait dans un fil différent.

+0

+1, la méthode (ou la propriété?) Que vous cherchez est l'invocation requise – masfenix

+0

Donc, je devrais utiliser Invoke pour toutes les propriétés, même celles qui fonctionnent sans elle (comme IsDisposed)? –

+0

J'utilise InvokeRequired pour accéder à la propriété Text, par exemple, je suppose que ma question est plus proche de ce que j'ai besoin de toujours utiliser Invoke, ou juste pour les propriétés qui à travers l'exception "cross-threading"? –

1

La façon la plus simple est d'utiliser:

Delegate Sub SetTextCallback(ByVal [text] As String) 

Private Sub SetText(ByVal [text] As String) 
' InvokeRequired required compares the thread ID of the 
' calling thread to the thread ID of the creating thread. 
' If these threads are different, it returns true. 
If Me.lboxResults.InvokeRequired Then 
    Dim d As New SetTextCallback(AddressOf SetText) 
    Me.Invoke(d, New Object() {[text]}) 
Else 
    Me.lboxResults.Items.Add([text]) 
End If 

End Sub

Désolé pour le code VB ...

0

Une autre option consiste à utiliser SynchronizationContext. Cela fonctionnerait non seulement pour WinForms, mais aussi pour WPF et ASP.NET, et il est disponible depuis .NET 2.0.

Appelez SynchronizationContext.Current sur le thread principal (par exemple dans le constructeur) et utilisez l'objet renvoyé chaque fois que vous devez synchroniser des appels. Si l'objet est nul, vous n'avez pas besoin de synchronisation.