【Grasshopper进阶】(未填坑)如何让Grasshopper Component创建后台进程,并对结果进行更新

如何让Grasshopper Component创建后台进程,并对结果进行更新

David Rutten的原文解答

If you really must use a thread to process data while you keep the Grasshopper GUI alive, then the approach would be something like the following:

  1. Your component is called upon to Solve itself for a Grasshopper Solution.
  2. It determines that a lot of data needs to be handled, so it starts a thread to do the heavy lifting and yields execution right back at Grasshopper, which then continues with null data (you’ll get a lot of orange components).
  3. Your thread is done processing data, it now wants to insert this data into the Grasshopper network, so it must Expire the original component, but it can only do this if no solution is running. So, it has to loop indefinitely until it finds a moment when the GH_Document.SolutionState is not GH_ProcessStep.Process. It should also check to see whether the GH_Document that contains the Component is in fact still in existence and active and whether or not the original component is still available or if it’s been deleted in the mean time.
  4. The thread must now Invoke a method on the Grasshopper GUI thread that will expire your component and initiate a new solution. If you call ExpireSolution(True) from a background thread, you will crash. Not just you, you will also crash me and probably Rhino. You can never, never ever call code that results in UI changes from a thread other than the main UI thread.
  5. Your component has now been expired and a new solution is running. It must have some mechanism in place which tells it whether it should start a new Background thread (a la point #2) or whether the thread it started last time is now ready for harvest. If the latter, extract the data from the thread and fill out the output parameters.

——David Rutton @ https://www.grasshopper3d.com/forum/topics/possible-to-add-background?xg_raw_resources=1&id=2985220%3ATopic%3A63596&page=1

关键点有3个:

  1. 判断当前画布上没有任何一个component正在running
  2. 利用GUI线程去调用ExpireSolution方法(如果有别的component正在running,调用ExpireSolution就会导致程序崩溃,这也是为什么要在第1点中判断)
  3. 这个component本身要能够判断后台线程是否计算完成

下面的示例代码中没有做第1步,只说明了2、3是如何做到的

示例代码

bool run = false;
bool havested = true;
int result = 0;

protected override void SolveInstance(IGH_DataAccess DA)
{
    if (run)
    {
        // Here to determine if a new solution had been triggered while 
        // last solution is still running.

        // either do something to cancel current running thread and start a new one
        // <!! do not forget to set up flags !!>
        // run = false;
        // havested = true;

        // or ignore the new solution request
        // AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Running!");
        // return;
    }

    if (havested)
    {
        int steps = 0;
        if (!DA.GetData(0, ref steps)) return;
        Message = "In progress";

        Action exp = () =>
        {
            OnPingDocument().FindComponent(this.InstanceGuid).ExpireSolution(true);
        };

        Action<ThisComponentClass, IGH_DataAccess, int> action = (comp, da, st) =>
        {
            try
            {
                int res = GoSolve(st);
                comp.Message = "Calc Completed";
                this.result = res;
                Grasshopper.Instances.DocumentEditor.Invoke(exp);
            }
            catch (OperationCanceledException)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Canceled.");
                comp.havested = true;
                comp.run = false;
                return;
            }
        };
        Task t = Task.Run(() => action.Invoke(this, DA, steps), cToken);
        run = true;
        havested = false;
        return;
    }
    DA.SetData(0, result);
    run = false;
    havested = true;
}

private int GoSolve(int steps)
{
    int res = 0;
    for (int i = 0; i < steps; i++)
    {
        res += i;
        if (GH_Document.IsEscapeKeyDown())
        {
            throw new OperationCanceledException();
        }
        Thread.Sleep(100);
    }
    return res;
}

其中第2点如何利用GUI线程去调用ExpireSolution是使用Grasshopper.Instances.DocumentEditor.Invoke方法,可以写成


    Grasshopper.Instances.DocumentEditor.Invoke(
        new Action( () =>
        {
            OnPingDocument().FindComponent(this.InstanceGuid).ExpireSolution(true);
        }
    ));
参考资源链接:[Grasshopper 3.0教程:从入门到高级设计](https://wenku.csdn.net/doc/4v25hc9hm7?utm_source=wenku_answer2doc_content) Grasshopper是一款强大的视觉编程工具,它允许设计师通过图形化界面创建复杂的算法和几何形状。为了帮助你掌握使用Grasshopper 3.0创建基本3D形状并进行参数化调整的技能,这里推荐《Grasshopper 3.0教程:从入门到高级设计》。 首先,你需要安装并熟悉Rhino软件,因为Grasshopper是作为Rhino的一个插件来使用的。创建一个基本的3D形状,比如一个盒子,你可以通过Grasshopper中的“Box”组件来实现。接着,你可以使用“Slider”组件来创建一个可调整的参数,它将允许你动态地修改盒子的尺寸。 为了进行参数化调整,你可以在Grasshopper中定义几何体的各个维度为参数。例如,通过“Number Slider”组件来控制盒子的长、宽、高,并将它们连接到“Box”组件的相应输入端口。此时,移动滑块就可以实时观察到盒子尺寸的变化。 在掌握了基本的3D形状创建和参数化调整之后,你可以进一步学习如何使用“Curve”组件来创建复杂的几何形状,以及如何结合使用“Surface”和“Mesh”组件来处理这些形状的表面细节和结构强度。通过这些操作,你可以逐渐构建起更为复杂的设计工作流程。 《Grasshopper 3.0教程:从入门到高级设计》不仅包含了基础概念的讲解,还深入到高级设计方法,帮助用户全面理解和掌握Grasshopper的强大功能。通过这本书,你可以系统地学习如何利用Grasshopper进行参数化设计,逐步构建起自己的设计语言。当你熟练掌握了基础操作后,鼓励你继续探索更高级的视觉编程技巧,并在Grasshopper社区中分享你的作品,以获取反馈和灵感。 参考资源链接:[Grasshopper 3.0教程:从入门到高级设计](https://wenku.csdn.net/doc/4v25hc9hm7?utm_source=wenku_answer2doc_content)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值