Start-RbThreadJob: Run one script from another (in same run process)

Characteristics

The Start-RbThreadJob cmdlet has the following characteristics:

  • Will run CB scripts asynchronously in a separate thread from the process in which it is invoked.

  • Can take either a Readibot TaskName (-TaskName) or a ScriptBlock (-scriptblock) to execute, but you not both in the same command.

  • Allows an argument list (-ArgumentList) to be passed in. The argument list be passed in using a Dictionary variable which is similar to the Start-CbJob cmdlet.

  • Unlike Start-RbJob, the script executed by the Start-RbThreadJob command is done in a separate thread but is just an extension of the calling script and the job that ran it.

  • Script blocks inherit the same Readibot session variables that every RB job environment has setup. This includes $ConnectId, $ConnectIds, $SessionVars as well as a few others.

  • Variables defined in the calling script are not accessible in the RbThreadJob. If you want the RbThreadJob to have access to variables from the calling script, you will need to pass them into the RbThreadJob using the “-ArgumentList” option.

  • Since the task is executed from a thread in the process of the calling script, it runs underneath the same $ConnectID as the main process.

  • Tasks or script blocks that are executed by this new command are treated as extensions of the calling script and not separate jobs with their own script ID and run ID. Execution will be registered underneath the calling scripts script ID and run ID.

  • An option ThrottleLimit (-ThrottleLimit) parameter can be set that sets the max. number of threads to spawn.

  • If throttleLimit value is reached, jobs will queue up and will execute when new thread becomes available.

  • Default throttleLimit value is set to 10 threads.

  • An argumentList and throttleLimit can be provided when executing a script or task.

  • You can specify a script block or a task to be executed but you can not specify them at the same time.

Command Syntax

 

Start-RbThreadJob -TaskName "path to bot" [-ArgumentList arglist] [-ThottleLimit threadlimit]

Or

Start-RbThreadJob -ScriptBlock "script" [-ArgumentList arglist] [-ThottleLimit threadlimit]

Where:

  • Taskname is the path and name of the task/script that you want to execute.

  • Arglist is a dictionary which contains the arguments and their values that will be passed to the task or scriptblock.

  • Script is text of a valid script to be executed.

  • ThrottleLimit is an integer value indicating the maximum number of RbThreadJobs that can be active at one time. The default is 10.

Start-RbThreadJob Examples

# Run bot task './get-process' $job = Start-RbThreadJob -TaskName './get-process' # Run a script block, which runs the get-process command. $job = Start-RbThreadJob -ScriptBlock "get-process"

ArgumentList Example

The ArgumentList is a dictionary object which you add parameters of different times. You add basic data types like “string”, “int”, ”bool”, “datetime” as well as more complex types like “xml”, “array” and “hashtable” types. In this example, we will pass a “string”, “int” and an “array” data type. The first step is to define and then insert the arguments into the ArgumentList dictionary.

Start-RbThreadJob Queue

You can submit a RbThreadJob even if the number of RbThreadJobs running is already at its maximum limit. RbThreadJobs are queued in a in-memory queue and when a free slot opens up, it will automatically be allocated a thread and executed. Like “ThreadLimit”, there is no maximum number of jobs that can be queued, it going to depend on the amount of resources available. In the future, it may make sense to have some maximum value and if exceeded we could throw an exception indicating that max. jobs queued has been reached. On the bright side, it appears that a very large number of RbThreadJobs can be queued without issue during my testing. For example, I ran tests where I would submit 500 and even 1000 RbThreadJobs, using the default thread limit of 10. So, at any one time, there was only 10 threads running, the rest of the RbThreadJobs were queued up waiting to be processed.

Job Commands

Job commands that have been tested with a RbThreadJob are Get-Job, Wait-Job, Receive-Job, Remove-Job and Stop-Job. There may be other Job commands that may or may not work. The only ones verified are the ones listed here.

 

Brief summary of a few of the Job commands

Get-Job

Gets the RbThreadJob object

Receive-Job

When you run a background job, the results do not appear immediately. To get the results (output) of a background job, use the Receive-Job cmdlet.

Wait-Job

Waits for one or more RbThreadJobs to complete

Remove-Job

Deletes a RbThreadJob

Stop-Job

Stops a RbThreadJob

Wait-Job

After you start a RbThreadJob, if you do not eventually do a Wait-Job, then the calling script will continue and if the calling script ends, then the RbThreadJob will be terminated. For example, if you were to run the following script ‘../script1’ and the script usually takes minutes to finish processing, then calling it from a script without a “wait-job”, would cause it to terminate prematurely. For example, the following command by itself would not work:

But if we add a “wait-job” it will function properly.

However, if we did a “wait-job” right after every “Start-RbThreadJob”, then this would not provide any level of multithreading or concurrency.

 

In this example, we start (3) RbThreadJobs where each job may take several minutes each. In order to increase performance, we want to use the Start-RbthreadJob to run

and we put the “wait-job” command after the last RbThreadJob has been started. This will allow (3) independent RbThreadJobs to be started and run concurrently but the calling script will wait for all (3) jobs to complete before moving on to the next stage.

If you have any output that you want to receive from the RbThreadJob, including regular script output, write-debug, write-information, etc., then you must issue a “Receive-Job” command, after the RbThreadJob has completed. Do not you use “Receive-Job” to get RbThreadJob output while it is still running or you risk losing output data. Only use after a “wait-job” command to ensure that the RbThreadJob is no longer running.

Here is an example of running a RbThreadJob, waiting for it to complete, and then receiving its output, which is then written to standard out.

You can also do the following:

Or you can pipe the job to wait-job and then to receive-job in one line and it will return the output in the $scriptJobOutput variable.