SolveIntance() updates the outputs only in the first time

Hi All,
I am facing a strange behavior in SolveInstance() method when using a class which implements asynchronous programming. The component only updates the outputs for the first time after running an asynch operation. after that the SolveInstance() runs but without chaining the output. I had the same component with method calling the ExpireSolution from an asynchronous thread and it was working just fine! any idea why using asynch-operations cause this issue?

Hi,

If possible, could you create a minimal example to share? There could be many things going wrong, but in general I don‘t think concurrent programming is well suited to Grasshopper. I could imagine whenever you expire the solution you are not invoking this on the GUI thread where Grasshopper runs.Get the Dispatcher object of Gh or Rhino to do that.

Furthermore, instead of async await, simply use Task.Run().I don‘t see how async really fits in?! Also if you are using any flags to determine the state, make sure these are marked as volatile once you access them from multiple threads.

Hi Tom, Thanks for your reply, I managed to solve the problem using couple of flags. I have post the complete code as a template on my blog , it maybe useful for others, please take a look and let me know what do you think…

Thanks for sharing @torabiarchitect ,
I was browsing your blog a bit and noticed that the github link of the doubly connected edge list is broken.
Would it be possible to see the code anyhow?
Also, really nice work on the ui,thanks for sharing!

I’m not sure if I fully understand all the code. It seems you are using an approach before C# 5 and Net framework 4.5 was introduced, and no async/await and the Task library was present and concurrent and parallel programming was a pain. Also, not using Lambda expressions with later introduced Action<T>/Func<T> delegates makes the code appear quite bloated for what you are doing. Great is the implementation of the CancellationToken, which allows to abort the operation. But you can also implement that with Task.Run(…, token).

See how simple you can do it with more modern C# (Faked as Console app):

public class Example
    {
        private enum ProgramState { Unknown, Creation, Finished}
        private volatile ProgramState _state = ProgramState.Creation;        
        private readonly List<Task> _tasks = new List<Task>();
        public Example()
        {           
        }

        public void SolveInstance()
        {
            if (_state == ProgramState.Creation)
            {
                _tasks.Clear();
                _tasks.Add(Task.Run(() =>
                {
                    // Simulate Work
                    Thread.Sleep(300);
                    Console.WriteLine("task 1 did something...");
                }));
                _tasks.Add(Task.Run(() =>
                {
                    // Simulate Work
                    Thread.Sleep(200);
                    Console.WriteLine("task 2 did something...");
                }));
                _tasks.Add(Task.Run(() =>
                {
                    // Simulate Work
                    Thread.Sleep(500);
                    Console.WriteLine("task 3 did something...");
                }));
                // final action
                Task.WhenAll(_tasks).ContinueWith(finalTask =>
                {
                    _state = ProgramState.Finished;
                    // Don't know the correct syntax
                    Console.WriteLine(
                        @"Rhino.RhinoApp.InvokeOnUiThread(new Action(() => this.ExpireSolution(true)));");
                    
                    // ! Instead I fake Expire solution. Remove that in GH:
                    SolveInstance();
                });
            }   
            else if (_state == ProgramState.Finished)
            {
                Console.WriteLine("Append data to output...");
                _state = ProgramState.Creation;
            }
        }
    }

Depending on the Framework version you may need to write new Action(() => {...}) instead of () => {...}

Hi Tom, Great feedback!, I actually used the same style using Task.Run() then wait for all to finish, this also worked and the code was much more clear compare to operation manager. Now imagine you have a search problem (for example a graph search or a dynamic program) in which in one of the tasks you may find the solution to your problem and you no longer need to wait for all other the tasks to be completed. What would be the easy work flow? I found it easier with asynch-programming where you can listen to an event which raises upon completion of each task. Can you tell me how would you do it in your approach?

Instead of WaitAll you can use WaitAny(_tasks, optionalTimeout). You might also think about aborting the others then, by a CancellationToken or much simpler by a volatile boolean. I mean, it’s probably a recursive loop you can break out of if any of your task has found a solution.

waitAny will return the index of the task if I remember correctly . right?

Thanks for reporting the broken link, I will fixed it soon

Correct, from Msdn:

Returns

Int32

The index of the completed task in the tasks array argument, or -1 if the timeout occurred.

cool! I will update my post with your snipped code , do you mind? if you have it somewhere on your personal website or something I would rather share a link
thanks

Don’t worry, do what you want. Maybe you add a link to this discussion.

the link should work now

1 Like