views:

327

answers:

3

If I am setting the Text property of a Form from a non-UI thread, then I need to use Invoke to avoid a cross-thread error. But, I can read the Text property without using Invoke. Is this safe? If I try to read the Handle property of a Form I get a cross-threading error. If I read the IsDisposed property of a Form it works fine. How can I tell when I need to use Invoke? Should I always be using Invoke to read and write property values?

+3  A: 

Whenever you are in a thread other from the UI thread you should use Invoke when accessing UI objects. Use InvokeRequired property to find out if you are in fact, in a different thread.

configurator
+1, the method(or property?) your looking for is the invoke required
masfenix
So I should use Invoke for all properties, even ones that work without it (like IsDisposed)?
Jon Tackabury
I am using InvokeRequired to access the Text property, for example, I guess my question is more along the lines of do I need to always use Invoke, or just for properties who through the "cross-threading" exception?
Jon Tackabury
Always use Invoke (or BeginInvoke). Just because a property happens not to throw an exception doesn't mean it's safe. The docs for InvokeRequired explain what's safe to do on the "wrong" thread.
Jon Skeet
Thanks Jon. It always seemed a bit hit or miss, so I have tended to use Invoke for almost everything. I'll update my code to always use Invoke.
Jon Tackabury
+1  A: 

The easiest way is to use:

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

Sorry for the VB Code...

JFV
A: 

Another option is to use SynchronizationContext. This would work not only for WinForms, but also for WPF and ASP.NET, and it is available since .NET 2.0.

Call SynchronizationContext.Current on the main thread (e.g. in the constructor), and use the returned object whenever you need to synchronize calls. If the object is null, you don't need synchronization.