Its been long understood that it is unsafe to call methods and properties on Windows controls unless you are on the same thread that created the control. Windows controls have always been designed with single threaded environment in mind. In .NET 1.1 you could actually perform the operations and on the whole things did seem to work, until perhaps the application is deployed and then it breaks….Thankfully in 2.0 MS have added programmatic protection when the your application is connected to a debugger, and will fire an InvalidOperationException.
To work around this issue you can deploy the standard InvokeRequired pattern, were by you call InvokeRequired method on the control you wish to access and if that returns true call BeginInvoke on the control passing it a delegate instance that represents the work you wish to have carried out on the controls owning thread. Hold on you said you can’t access a control unless you are on its owning thread, that’s true in the whole accept for some select methods
- InvokeRequired
- BeginInvoke
- Invoke
- CreateGraphics
The above list was my understanding before today, but what I realised today was that another method can be added to the list. This holy method is Invalidate… I stumbled upon this whilst creating a more funky progress bar control. The control had a progress property that was being set by my background task, and once set called invalidate In order for the progress bar to be updated, this produced no exception when the invalidate was called from the non owning thread, leading me to conclude that it is perfectly safe to do so….
Which makes sense when you think about it since all it is doing is telling the OS that it needs to generate a Paint event for a given control, which ultimately will be delivered on the message queue for that controls owning thread. Since there is no underlying control interaction on the non UI thread no exception is raised.
No comments:
Post a Comment