McNeel Wiki
Dot Net Event Watcher
edit · print · help · all topics
Main Pages

AccuRender

Bongo

Brazil r/s

Developer

Flamingo

Penguin

Rhino Blogs

Rhino

Rhino Labs

Search

Languages

Česky

Deutsch

English

Español

Français

Italiano

Polish

日本語

한국어

中文(繁體)

 
.

If you have some controls that are using an event watcher to synchronize a control's appearance with what is going on in Rhino, please read the following.

The virtual function inside your event watcher class potentially could be called from a thread that is NOT your main user interface thread. This happens in the case where a long running command has started a thread to allow a user to cancel a command. A sample case where this occurs is in the contour command and the OnAddObject virtual function.

Why is this of any interest to you?

Windows applications can not update any user interface from any thread other than the main UI thread. Changing a Windows Forms control property typically causes the control to immediately update its display. When this happens, windows will crash the application.

So... what can I do about this?

If you are updating a control from inside your event watcher virtual function, you should check to see if InvokeRequired on your control is equal to True. If this is the case, you must invoke a delegate to handle your UI updating. This is actually easier than it sounds.

Here is a VB.NET sample of OnAddObject inside of your event watcher subclass

 Public Overrides Sub OnAddObject(ByRef doc As MRhinoDoc, ByRef obj As MRhinoObject)
  'm_ctrl is your windows forms control that you want to update
  If( m_ctrl.InvokeRequired ) Then
    'This code is being called inside a non-ui thread. You should not updated your
    'control from this thread
  Else
    'It is fine to update your control
    m_ctrl.Text = "OnAddObject was called"
  End If
 End Sub

But... I really do need to update my control's state even when in the wrong thread!

This is where Invoke or BeginInvoke comes into play. You can tell your control that your want it to run some code in the main UI thread. Here is a VB.NET sample of how to do this. Again this would all be inside of your event watcher subclass.

 'delare a delegate
 Private Delegate Sub OnAddDelegate( text as String )
 Private Sub SetControlText( text as String )
   m_ctrl.Text = text
 End Sub


 Public Overrides Sub OnAddObject(ByRef doc As MRhinoDoc, ByRef obj As MRhinoObject)
   If( m_ctrl.InvokeRequired ) Then
     m_ctrl.BeginInvoke( New OnAddDelegate(AddressOf SetControlText), "OnAddObject was called" )
   Else
     SetControlText( "OnAddObject was called" )
   End If
 End Sub

The above function could be rewritten to just always call the delegate

 Public Overrides Sub OnAddObject(ByRef doc As MRhinoDoc, ByRef obj As MRhinoObject)
   m_ctrl.BeginInvoke( New OnAddDelegate(AddressOf SetControlText), "OnAddObject was called" )
 End Sub
rename · changes · history · subscriptions · lost and found · references · file upload