RunScript in a thread


#1

Hi,

I want automatize a process in rhino without human intervention.

The idea is that the user start the application in automatic mode, then one process imports a file and it begin to work.

The process is a BackGroundWorker, and when I want run a Script, for example:

Rhino.RhinoApp.RunScript("_-AgutAutomatization", true);

It not works, or the RunCommand is not exec.

If I run this command out of backgroundworker, the command is exec

I’m using RhinoCommon and c#


#2

You need to invoke your command on a UI thread. It seems any use of the RhinoScript object requires running on the UI thread.

If this were WPF I would do the following code:

Application.Current.Dispatcher.Invoke(() => {
Rhino.RhinoApp.RunScript("_-AgutAutomatization", true);
});

Winforms I believe you can just use the Form object and call either Invoke or BeginInvoke and your method.


(Dale Fugier) #3

There is not enough information here for us to answer your question.

Keep in mind that Rhino is not thread-safe. So if your script is working with document objects, you are not going to be successful.

What is “AgutAutomatization?” Is it a command you added in a plug-in?

More details as to what you are trying to and why would be appreciated.


#5

Ok,

I try explain better:

I want automatize a process that it has this steps

  1. Read a file to get the path of a 3dm file
  2. Import the file
  3. Get the objects in determined layers
  4. Process
  5. Write a file with the results

Repeat the process

The functions from 2 until 5 works with human intervention doing click on buttons.

But now, I need do this process automatically.

My idea is, open my plugin in automatic mode, and then a BackGroundWorker start.

  • Step 1 is made by “AgutAutomatization” command.
  • Step 2 is made with a command. AgutImportDXF
  • Step 3…5 are functions

So, when I the backgorundworker calls

Rhino.RhinoApp.RunScript("_-AgutAutomatization", true);

The command is not exec.

and jstevenson72:

Dispatcher.CurrentDispatcher.Invoke(() =>
{
Rhino.RhinoApp.RunScript("_-AgutAutomatization", true);
});

I get an error: cannot convert lambda expression in ‘System.Delegate’ because isn’t a delegate type.

I try do it:

private delegate void AutomatizationDelegate();

AutomatizationDelegate automatizacion = new AutomatizationDelegate(Automatizacion);
Dispatcher.CurrentDispatcher.Invoke(automatizacion);

private void Automatizacion()
{
Rhino.RhinoApp.RunScript("_-AgutAutomatization", true);
}

But neither the script runs


PythonScript ExecuteFile Command Throw an error
#6

Manolo,

I assume you are in fact doing this within a WPF application. So I wrote some sample code you can put into a Rhino Common Command that will demonstrate how to invoke onto a WPF UI Thread from a Background Worker Thread.

  1. Create a Rhino Command in your Project.

  2. Add the following Code / Methods to the Command.

    private static BackgroundWorker _worker;
    private Application _app;
    
    protected override Result RunCommand(RhinoDoc doc, RunMode mode)
    {
        // Start WPF UI Dispatcher if not running.
        if (_app == null)
        {
            _app = new Application();
        }
    
        RhinoApp.WriteLine("Creating Background Worker Test.");
    
        _worker = new BackgroundWorker();
        _worker.DoWork += _worker_DoWork;
        _worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
        _worker.RunWorkerAsync();
    
        RhinoApp.WriteLine("Exiting Run Command.", EnglishName);
    
        return Result.Success;
    }
    
    void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        RhinoApp.WriteLine("DoWork Completed Back on UI thread.", EnglishName);
    }
    
    void _worker_DoWork(object sender, DoWorkEventArgs e)
    {
        const string command = "_-Circle p 0,0 3,3";
    
        RhinoApp.WriteLine("Background Worker DoWork Starting on Background Thread.");
    
        var result = RhinoApp.RunScript(command, true);
    
        RhinoApp.WriteLine("Circle Attempted: " + result);
    
        Application.Current.Dispatcher.Invoke(() =>
                                            {
                                                RhinoApp.WriteLine("Background Worker DoWork Invoking on UI thread.");
    
                                                result = RhinoApp.RunScript(command, true);
    
                                                RhinoApp.WriteLine("Circle Attempted: " + result);
                                            });
    }
    
  3. Start your project and Execute the Command.

  4. You should see the following Output in the Command Prompt window.

Creating Background Worker Test.
Exiting Run Command.
Background Worker DoWork Starting on Background Thread.
Circle Attempted: False
Background Worker DoWork Invoking on UI thread.
Command: _-Circle
Center of circle ( Deformable Vertical 2Point 3Point Tangent AroundCurve FitPoints ): p
Start of diameter ( Vertical ): 0,0
End of diameter ( Vertical ): 3,3
Circle Attempted: True
DoWork Completed Back on UI thread.

This demonstrates that the RunScript() executed on the Background Thread fails, but by using the Dispatcher and Invoking your RunScript the second time it succeeds. You will have a Circle near Origin Axis.

This should fix you all up. If you have any questions don’t hesitate to email me.


#7

Thank you very much jstevenson72