I’ve created a context manager that I use in the plugin I work on, that looks like this:
class pause_redrawing:
def _on_enter(self):
self.previous_redraw = rs.EnableRedraw(False)
def _on_exit(self):
rs.EnableRedraw(self.previous_redraw)
def __enter__(self):
Rhino.RhinoApp.InvokeOnUiThread(System.Action(self._on_enter))
def __exit__(self, exc_type, exc_inst, exc_tb):
Rhino.RhinoApp.InvokeOnUiThread(System.Action(self._on_exit))
This can then be used like:
# async: true
with pause_redrawing():
# delete some stuff
# add some stuff
# etc.
# do more stuff
The InvokeOnUiThread
makes this work both in synchronous and asynchronous commands. If I remove this and call either _on_enter
or _on_exit
directly, this crashes Rhino on Macs when run through an asynchronous command. This does not crash Rhino on Windows machines. The advantage of being able to do this without the invoke is that I can guarantee the background thread won’t add/remove geometry before redrawing is paused or after it’s unpaused. To get this behavior without crashing Macs, I could use Rhino.RhinoApp.InvokeAndWait
, but this adds an artificial delay which slows things down a lot. My understanding is that the delay is necessary because there’s a flag that both the UI thread needs to set to indicate that it’s done, and the background thread wants to check the value of this flag, but because of resource sharing between threads and whatnot, checking constantly would slow both threads down significantly, so it’s better to just add a delay in the background thread’s while (!done)
loop because it’s going to be waiting anyways. I’m not too familiar with multithreading and shared resources in C#, and I haven’t tried recreating that while (!done)
loop on the Python side using something like threading.Event
.
Some other things that I’ve also seen crash Rhino only on Macs:
-
Adding/removing layers from an async thread (guaranteed in at least SR 8.9.24194.18122, but might still be a problem in SR 8.11 because changing the document’s redraw parameter still breaks in the latest SR)
- Regardless of whether or not redrawing is on
-
Changing the active layer from an async thread (guaranteed in at least SR 8.9.24194.18122, same as above)
At this time, I only have a few stacktraces, all from SR 8.9.24194, but I know the set_RedrawEnabled stacktrace (or one very similar to it) is still being seen in the latest SR. I only have Windows machines handy to test on, so these reports have to be sent to me from users with a Mac.
set_RedrawEnabled crash from async thread (click for more details) SetCurrentLayerIndex crash from async thread (click for more details)I’m not surprised that Rhino crashes here (after all, the stacktraces make it pretty clear that modifications to the layout engine from a background thread are a no-no), but what’s weird is that these specific crashes only happen on Mac, not on Windows.
2 posts - 2 participants