It was a bitter tear to fall into the pit of grasshopper.
The following is an issue discussed on the Grasshopper platform:
Http://www.grasshopper3d.com/forum/topics/triggering-solution-refresh
A comment from Daniel David Rutten, which I translated as follows, is for communication only:
Of course this is the 2011 thing, the subsequent update I will make up!!
1. Expiresolution (True) vs. Expiresolution (false) vs. Newsolution (true) vs. Newsolution (false)
When you end the call, which or what method is called? This basically depends on how often you want these events to occur, and whether you want to update individual components or update multiple components at once. These methods are done in the following ways:
expiresolution (True): The component you are invoking this method on, and all components that depend on it, are set to the "Terminate" flag, which basically equals its downstream. When these flags are set to complete, it will call Gh_document.newsolution (False).
expiresolution (False): almost ibid, except that it does not notify the file to re-calculate itself. Use this method if you want to terminate all components before starting a new calculation process.
newsolution (True): This sets the "STOP" flag for all components in the file, and calculates everything, this is carpet bombing, you'd better not use.
newsolution (False): This will re-calculate the objects that are set to the "Stop" flag.
To summarize, you should use this in the following scenarios:
- An object has changed, and we want to immediately re-calculate it (for example, the user drags a slider or joins a line). call Expiresolution (True)
- Due to some out-of-field factors, one-vote object was terminated at the same time (or almost simultaneously). For example, you want to mount multiple hardware controllers or sensors and they are always triggering updates. call Expiresolution (false) on all affected components, and then call Newsolution once (false)
- A big event happened, but you don't know what's going on. call Newsolution (True) because you do not have enough information to prevent the cache data from being corrupted.
Grasshopper does not have enough intelligence to postpone the calculation until it determines that no expireobject () call is coming in. If you let him go and weigh it, it will be counted immediately. If you need to delay intelligently, you need to write your own code.
2. Thread-based Applications vs. thread-not-based applications
Grasshopper is not a thread-based application, as the name implies, the interface portion of any framework application is single-threaded. This can be problematic when you receive an external event on another thread, possibly a hardware control signal, and possibly a sensor data.
The reality is this:
For some reason, the grasshopper file is terminated, and the Newsolution () method is called in order to fix the unknown error. First it looks at the components in the file in turn, and tells it to recalculate whenever a component's "Stop" flag is found to be true. If a component depends on a component that is not finished (' solved '), it cannot be recalculated. This may result in a heavy shockwave of the entire file. Finally, when all inputs are available, the component is finally re-calculated and the control is returned to the file solver.
The file solver is now continuing to look for its "terminated" component. It may be that this is the case, or it could have been a terminated component, and the component that might have been found already had the rest of the terminating component reset, so that the file Solver had nothing to do.
When the file Solver has checked all objects, and there are no "terminating" components, it calls Grasshopper Canvas and Rhino viewports for repainting.
This is the correct, single-threaded solution process. If two or more threads are executed in the same file, the gates of Hell are opened.
Let's imagine that the file Solver is solving the problem of a terminated object, when the external event of another thread occurs, and the event is immediately processed by the corresponding component response. This component now calls Expiresolution (True), which causes the "terminate" flag of the one-vote component to be set. Some of these components may have been processed by the file processor in the first thread, even though the file processor thought they had handled them perfectly, but they were terminated again. Other components may still be in the "terminating" state because the file processor has not yet reached them. The worst case scenario is that a component has already computed the results in the first thread and is successfully received by subsequent data streams, and the second thread erases the data during the receive process, which causes a mismatch and is likely to crash.
The Grasshopper core algorithm is not thread-safe, and if you call a different thread method, you will fall into a crash.
What you need to do is "call" your first thread from inside your second thread so that the first thread can finish what it is doing before responding to your request. When you write a multithreaded application with the GUI, the call is a very important concept, there are a lot of resources on the Internet to explain how it works, here are 2 of them:
Http://weblogs.asp.net/justin_rogers/pages/126345.aspx
Http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
Original:
Hi Eric,
There ' s multiple issues here, I'll address them in separate posts.
1) expiresolution (true) vs. Expiresolution (false) vs. Newsolution (true) vs. Newsolution (false)
which method (s) you end up calling depends a lot in how often do expect to get these events and whether or don't you want t o Update a single or multiple the same time. The methods do respectively:
expiresolution (True): It sets the ' expired ' flag on the component-call this method on and all objects that depend on that component . Basically everything downstream of it. When it's done setting all these ' expired ' flags, it'll place a call to Gh_document.newsolution (False).
expiresolution (False): Does the same as the previous one, except it doesn ' t tell the document to re-solve itself. Use the If you want to expire a bunch of the different components before attempting a new solution.
newsolution (True): This would set the ' expired ' flags of all components inside the document and resolves everything. This is carpet bombing, rarely should.
newsolution (False): This would only be resolve those objects that has their ' expired ' flags set.
So, to recap, given the following cases your should be using the associated approach:
-a single object is changed and we want to immediately resolve (for example when a user drags A number slider, or Connec TS a wire). Use expiresolution (True).
-A bunch of objects is expired simultaneously (or nearly simultaneously) by some sort of massive off-site event. For example if-hook up multiple hardware controls or sensors and they ' re all firing updates all the time. Use Expiresolution (false) in the affected objects, then place a, and then place a, and to Newsolution (false).
-Something massive had happened and you had no idea about what exactly it was. with Newsolution (True), as you don't have enough information to limit the devastation of cached data.
Grasshopper is not a smart enough to Post-pone solutions briefly until it decided this no more calls to Expireobject () is C Oming in. If you have it to recompute, it'll immediately recompute. If you need delayed smarts, you'll need to write those yourself.
2) Threaded Application vs. non-threaded applications.
Grasshopper is a non-threaded application and by definition, the interface portion of any WinForms apps is single-threaded. This poses problems if you get external events that occur on a different thread, as might well being the case for hardware Controls or sensor data.
Here's essentially what happens:
Something expires (part of) a Grasshopper document, and the Newsolution () method is called upon to rectify this. It starts by iterating through all the objects inside the document and whenever it encounters a object which has the ' expire d ' flag set to True, it'll tell it to recompute itself. This object cannot recompute itself unless all the objects it depends on is also ' solved ', so it might cause a shock-wave of recomputes across the entire document. Eventually though all the inputs is available and it recomputes itself and then hands control back to the document Solver .
The document Solver now continues in its quest to find more ' expired ' objects. It might find some in which case the above stories is repeated, or maybe there were only ever one expired object, or maybe th E object We just found caused all other expires objects to solve themselves, leaving nothing to do for the document Solver .
When the document Solver have iterated over all the objects and determined that none of them is still ' expired ', it'll p Lace a call to redraw the Grasshopper canvas and the Rhino viewports.
That's what happens during a proper, single-threaded solution. When there ' s and threads operating on the same document, all hell breaks loose:
Let's assume the document solver is halfway do with its Job of resolving all expired objects. At the a external event comes in on a different thread, which is handled immediately by some component. This component places a call to expiresolution (True) , which sets the ' expired ' flags of a bunch of component S. Some of these components would already has been handled by the Solver on the first thread, so even though the solver th Inks all are fine and dandy, these components has in fact expired again. Other components might still is expired because the Solver hasn ' t gotten to them yet. Worst case scenario, a component just finished solving itself on the first thread and the data inside of it are being Harve Sted by a downstream Component. while it's collecting this data the second thread wipes the data, causing a mism Atch and probably a crash.
The Grasshopper core algorithms is not thread-safe and if your start calling methods from different threads, you'll run Into clashes.
What are need to does is ' invoke ' of the first thread from your second thread. That's the first thread is allowed to finish what it's doing before getting around to your request. Invoking is a very important concept if you ' re writing a multi-threaded app with a GUI and there ' s plenty of online Reso Urces explaining how it works. Here's the "s":
Http://weblogs.asp.net/justin_rogers/pages/126345.aspx
Http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
--
David Rutten
[Email protected]
Poprad, Slovakia
Popular Understanding Grasshopper Trigger Update/Multithreading