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
2009-02-11 19:07:32
+1, the method(or property?) your looking for is the invoke required
masfenix
2009-02-11 19:09:50
So I should use Invoke for all properties, even ones that work without it (like IsDisposed)?
Jon Tackabury
2009-02-11 19:10:40
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
2009-02-11 19:11:28
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
2009-02-11 19:14:08
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
2009-02-11 19:18:33
+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
2009-02-11 19:08:51
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.