I’m crashing my rhino when I throw in a Parallel.For() call in my c# script component, and I can’t figure out the cause.
What’s paralleled is the CreateNetworkSurface() method of Surface
Here’s my snippet for pattern. Abbreviated for legibility.
The code runs perfectly if I swap the parallel call with a foreach loop. With the parallel, it occasionally succeeds.
using System.Threading.Tasks;
using System.Linq;
// using more stuff
// omitted bunch of boilerplate codes
// my class object for parallel
protected class NWSrf{
// omited some variables
protected Curve[] crvs = null; // network curves
internal NurbsSurface srf = null; // result surface
public NWSrf(IEnumerable<Curve> c){
crvs = new Curve[c.Count()];
int i = 0;
foreach (Curve crv in c)
crvs.SetValue(crv.DuplicateCurve(), i++);
}
internal void MakeSrf(int ctn, double et, double it, double at){
srf = NurbsSurface.CreateNetworkSurface(crvs, ctn, et, it, at, out ei);
}
}
// the standard runscript in a C# component of grasshopper
private void RunScript(DataTree<Curve> C, ref object A)
{
// some variables
NWSrf[] nwsobjs = new NWSrf[C.BranchCount];
NurbsSurface[] nurbs = new NurbsSurface[C.BranchCount];
// make all the object for parallel
for (int bi = 0; bi < C.BranchCount; bi++){
nwsobjs.SetValue(new NWSrf(C.Branch(bi)), bi);
}
// compute in parallel
Parallel.For(0, nwsobjs.Length, bi => {
nwsobjs[bi].MakeSrf(2, 0.01, 0.01, 0.01);
});
// query the results of each objects
for (int bi = 0; bi < nwsobjs.Length; bi++){
nurbs.SetValue(nwsobjs[bi].srf, bi);
}
A = nurbs;
}
First, I think you shouldn’t refer to “newsobjs” in parallel actions
Parallel.For(0, nwsobjs.Length, bi => {
nwsobjs/*This can be accessed by multiple actions at the same time*/[bi].MakeSrf(2, 0.01, 0.01, 0.01);
});
You may need to pass the object “nwsobjs [bi]” to action like with Task(..., nwsobjs [bi])
Another option is to use ThreadPool.QueueUserWorkItem and CountdownEvent
You can also create a function to lock the current thread to guarantee synchronisation between multiple threads. That way only one thread is allowed to index your data. But this all depends if create network surface is a thread safe rhinocommon method.
ah thanks for testing it out!
the indexing within Parallel.For() actually works on many rhinocommon calls such as sweeping or boolean differences, although it does look like a bad practice.
really makes me think this network srf api has something else…
Dale, You are not missing anything. I’m missing Rhino 7. You guys have a release date yet? Or any plans to fix these in Rhino 6?
Also the some multi thread crashes don’t take place regularly. It may or may not happen at each solution. Completely erratic. For example, I’ve found that Sweep2 multi-threaded crashes about 1 in 10 solutions.