How to dispatch results back to the main thread in a grasshopper component

I’m writing a websockets component. All the work needs to be done in a separate thread due to the way the System.Net.WebSockets.ClientWebSocket code works. It’s all task based. When I receive a message from the websocket I call ExpireSolution(true) but sometimes that is causing an exception to be thrown

The critical part of the code is launched from SolveInstance

            Task.Run(async () => {  while (true)
                    _rx = await ReadString(_socket);

However the ExpireSolution line is what is triggering the exception from Grasshopper. I would assume there is some kind of way to dispatch a call back to the main thread like in WPF though I can’t find it.

Duplicate: System.InvalidOperationException: Cross-thread operation not valid

The answer is linked to in the next reply of that thread:

Interesting. I use a bit different algorithm:

  1. Start a task that asynchronously waits for a message from the external server.
  2. Once a complete message has been received, expire the solution, forcing a recompute. This clears all output parameters and calls SolveInstance() .
  3. In SolveInstance() :
    • Parse the message and populate the output parameters.
    • Go back to step 1, i.e. wait for the next message.

See my thread: DA.SetDataList: How to replace list?

This works fine. However, when I right click on the canvas and tell Grasshopper to Recompute, then an exception is thrown. The runtime doesn’t like a second webSocket.ReceiveAsync() to be run in parallel. This makes sense. One approach is to first stop the current task, but there I also ran into issues. Did you encounter this problem, and did you solve it?

Update: Solved the issue by introducing a variable receivingMessage that indicates whether the component is currently receiving a message. If that is the case, if will not start receiving another message in parallel.

Find my component on GitHub: feklee/san/grasshopper