How to tell if Invoke is required for a property?
-
22-08-2019 - |
Question
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?
Solution
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.
OTHER TIPS
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...
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.