How to use"DA.SetData(....)"from another thread?

(Andrealu2012) #1

I am doing a component for TCP server,to listen “string” from a client.
this is the sample code:

    protected override void SolveInstance(IGH_DataAccess DA)
    {
        int port = 0;
        DA.GetData("Port", ref port);
        thrListener = new Thread(new ThreadStart(Listen));
        thrListener.Start();
        DA.SetData("Output", outputStr);
     }
      private void Listen()
    {
         Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        listener.Bind(new IPEndPoint(IPAddress.Any, 59152));
        while (true)
        {
            listener.Listen(1);
            Socket socket = listener.Accept();
            NetworkStream ntwStream = new NetworkStream(socket);
            StreamReader strmReader = new StreamReader(ntwStream);
            outputStr = strmReader.ReadToEnd();

            Message = outputStr;
            Grasshopper.Instances.RedrawCanvas();
            
            socket.Close();
        }
    }

when i run the code,the “Message” can show realtime,but the DA’s output is empty…i try a lot of way,such as add use a global variable gDA to reference DA,and add “gDA.setdata(…)” in the While(true) {…},but it can not work…
so may be someone can have a way to invoke DA.setData in a workerThread.Thank you.

(David Rutten) #2

You should assign the value that comes out of the thread to a class level variable (not a global/static). This assignment will be atomic if the data is a reference type or a value type of 64 bits or less. You then trigger ScheduleSolution() on the document which contains your component. Register a callback with that schedule. In the callback expire your component. In the subsequent call to SolveInstance() assign your class level variable to your outputs.

You need all these steps because your process runs on a thread other than the UI thread.

1 Like
(Andrealu2012) #3

David @DavidRutten ,for example ,if run ScheduleSolution(10,callback),it means begin to run SolveInstance() at once,and 10ms later,“callback” is begin to run?
Thank you

(David Rutten) #4

GH_Document.ScheduleSolution(10, callback) is technically a request, not an instruction as such.

During a solution various objects may all request future solutions to be triggered after some delay. Whenever a new request comes in it is either ignored if another, earlier request already exists, or it overwrites the existing schedule with the earlier one.

Furthermore it depends on when the method is called. If it happens during a solution then the request is simply remembered and a timer for 10 milliseconds won’t be started until after the solution completes. If however you call this method while there is no solution running, a timer is started immediately.

The best way to think of a schedule is “a new solution will start after the current one finishes not much later than my requested delay”. It could be much earlier if someone else schedules a solution with a shorter delay, or even if the user does something which triggers a solution.

At any rate, if you schedule a solution and you provide a callback method, that callback will be called whenever the next solutions starts, no matter whether that’s much earlier than you requested. It will not be called again after that.

(Andrealu2012) #5

thank you David,and can i think this way? : when GH_Document.ScheduleSolution(10, callback) run,no run the SolveInstance() again…the only thing “GH_Document.ScheduleSolution(10, callback)” do is: run callback in the UI thread after some delay?

(David Rutten) #6

No it will run a new solution. The callback is there so you can prepare for this solution, for example by expiring the objects which you want to solve.