Why "await" does not work?

i wrote a component to do a long calculation work:


the function is :when input “true”,it output 0.516,when input “false”,it output 0.00
but you can see the picture above,the input is true,but the output is a tree data…and this output had to been shown by reconnect the component and panle.
this is the code:

 /// <summary>
    /// Registers all the input parameters for this component.
    /// </summary>
    protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
        pManager.AddBooleanParameter("B", "", "", GH_ParamAccess.item);
    }

    /// <summary>
    /// Registers all the output parameters for this component.
    /// </summary>
    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        pManager.AddNumberParameter("N", "", "", GH_ParamAccess.item);
    }

    /// <summary>
    /// This is the method that actually does the work.
    /// </summary>
    /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
    protected async override void SolveInstance(IGH_DataAccess DA)
    {
        bool b = default;
        DA.GetData("B", ref b);
        if (b == true)
        {
            double r = await GetLongtimeCaluculationAsync3();
            DA.SetData("N", r);
        }
        else
        {
            DA.SetData("N", 0f);
        }
        //ExpireDownStreamObjects();
    }
    Task<double> GetLongtimeCaluculationAsync3()
    {
        Task<double> a = Task.Run(() =>
          GetLongtimeCaluculation()
         );
        return a;
    }
    double GetLongtimeCaluculation()
    {
        double answer = 0;
        for (int j = 0; j < 10000; j++)
        {
            for (int i = 0; i < 5000; i++)
            {
                answer = Math.Sin(i) + Math.Cos(i);
            }
            answer = Math.Sin(answer + 1) + Math.Cos(answer + 1);
        }
        return answer;
    }

thank you for help!

Hi Andrealu2012,

I am not an C#-Expert, but in your code you are accessing the paramoutput pManager via a string, not an index.
I am not sure, if this is possible, but you could try to use an index instead, like “DA.SetData(0, r)” and “DA.GetData(0, ref b )”
You could declare the variable “r” before you change it.

double r = 0;
if(b)
{
r = await GetLongtimeCaluculationAsync3();
}
DA.SetData(0,r);

I hope it helps… I did not test it.

greetings,
Bumaye

@andrealu2012 Have you found a solution to this issue? I am having a similar issue when awaiting the GetAsync() method of HttpClient. The null entry is getting added to DA outputs once the awaited call returns.

For anyone having a similar issues, using a Task Capable Component has solved the issues for me.

Task Capable Components with C# (rhino3d.com)

Hi @jbarry thanks for bringing attention to this, i’m experiencing a similar issue, going to try and use your link.

cheers

Because Grasshopper doesn’t run with the async-await model and you should notice task-capable components merely parallelize inputs over branches and provide a responsive experience.

1 Like

Exactly. But not only that, the whole concept of Grasshopper is linear. You can parallelize one component, but it doesn’t make much sense to apply concurrent programming to a non-concurrent hosting app. The only reason I see is it to keep the UI responsive. But then you’re adding a feature, Grasshopper doesn’t have out of the box. And this is a problem.

If you want that, you basically have to run a solution multiple times to compute something once. It’s doable and not very hard to achieve, but the effort and the risks involved are in my opinion not worth the benefit you gain from it.