actualización 27apr2018: formatear reparación
Acabo de recibir una pregunta sobre el uso de varias instancias de RunProgram al mismo tiempo. Aquí hay un ejemplo que ejecuta tres copias de PING contra tres direcciones IP diferentes y registra los resultados en tres tablas de datos diferentes. El ejemplo muestra cómo usar el valor de "parámetro" para que cada Programa de Ejecución sepa qué tabla de datos usar. El archivo adjunto es igual que el código en línea ...
// first, we'll need containers that can be indexed from 1 to NJOBS
// and hold the references to the data tables and the RunPrograms.
datatab = Associative Array();
runprog = Associative Array();
who = {"jmp.com", "google.com", "bing.com"}; // each runProgram can do something different
NJOBS = N Items( who );
// next, a loop to make tables and launch the RunPrograms
For( iJOB = 1, iJOB <= NJOBS, iJOB++,
// make a table with a text column, then make the column wide so we can see more data
datatab[iJOB] = New Table( who[iJOB], addrows( 1 ), New Column( "text", Character, Set Values( {"pinging..."} ) ) );
datatab[iJOB]:text << setdisplaywidth( 500 );
// launch the RunProgram. It is particularly important to make sure the RunProgram
// object is stored in a variable that won't be overwritten...the associative array holds it.
runprog[iJOB] = RunProgram(
Executable( "PING.EXE" ), // this is the 'job' we are running several copies of, in parallel
Options( {"-n 10", who[iJOB]} ), // run for 10 seconds --- this is a PING option
Parameter( iJOB ), // remember which "instance" this is --- this goes to the ReadFunction
ReadFunction( // define a function that will get called for lots of small snippets of text
Function( {this, myInstance}, // myInstance is the iJOB
{buffer = ""}, // local to this instance. buffer up small snippets
While( this << canread, // this reads multiple snippets that may show up in a single call
buffer = buffer || (this << read); // put the snippets together
Wait( .01 ); // this isn't really needed except to get the snippets in a single record
); // gather as much as possible
buffer = Regex( buffer, "\s+", " ", GLOBALREPLACE ); // clean up the buffer, remove CRs and LFs
If( Trim( buffer ) != "", // see if we have something to say. there are blanks in PING's output
(datatab[myInstance]) << addrow( 1 ); // my table gets a new row
(datatab[myInstance]):text = buffer; // store the cleaned up buffer
);
)
)
);
);
// if you want to, you can wait for the runprograms. They *require* JMP to be idle to make
// the callback to the read function; the following polling loop uses wait(.1) to make sure
// JMP is mostly idle. When the PING program terminates, it closes the STDOUT file handle
// JMP is listening to, causing the isReadEof message to return TRUE.
For( iJOB = 1, iJOB <= NJOBS, iJOB++,
While( !((runprog[iJOB]) << isReadEof), Wait( .1 ) )
);
Write( "All Done!\!n" ); // now you can proceed with the data tables

Hay un límite a la cantidad de estos que puede ejecutar a la vez. Probablemente no cientos; utilizan recursos en su computadora que no son ilimitados.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />En JMP 11, podría modificar la secuencia de comandos para usar funciones de lectura únicas para cada instancia de RunProgram. Este ejemplo incrusta la variable "myInstance" en la lista de variables locales, con una asignación que resuelve el Eval (EvalExpr (... expr () ... mecanismo.
(Desactive la opción Traducir en la parte superior de la pantalla si el texto a continuación está desordenado).
// primero, necesitaremos contenedores que puedan ser indexados de 1 a NJOBS
// y mantenga las referencias a las tablas de datos y los Programas de Ejecución.
datatab = matriz asociativa ();
runprog = matriz asociativa ();
who = {"jmp.com", "google.com", "bing.com"}; // cada runProgram puede hacer algo diferente
NJOBS = N Artículos (quién);
// a continuación, un bucle para hacer tablas y lanzar los RunPrograms
Para (iJOB = 1, iJOB <= NJOBS, iJOB ++,
// haga una tabla con una columna de texto, luego amplíe la columna para que podamos ver más datos
datatab [iJOB] = Nueva tabla (who [iJOB], addrows (1), New Column ("text", Character, Set Values ({"pinging ..."})));
datatab [iJOB]: texto << setdisplaywidth (500);
// inicia el RunProgram. Es particularmente importante asegurarse de que el RunProgram
// el objeto se almacena en una variable que no se sobrescribirá ... la matriz asociativa lo contiene.
runprog [iJOB] = Eval (
Eval Expr (
Ejecute el programa(
Ejecutable ("PING.EXE"), // este es el 'trabajo' en el que estamos ejecutando varias copias, en paralelo
Opciones ({"-n 10", Expr (who [iJOB])}), // ejecutar durante 10 segundos --- esta es una opción de PING
// no en JMP 11: Parámetro (iJOB), // recuerda qué "instancia" es --- esto va a ReadFunction
ReadFunction (// define una función que será llamada para muchos fragmentos de texto pequeños)
Función ({this / * no en JMP 11:, myInstance * /}, // myInstance es el iJOB
{buffer = "",
// la forma JMP 11 ...
myInstance = Expr (iJOB) // evalexpr se encarga de esto
}, // local a esta instancia. amortiguar pequeños fragmentos
Mientras (esto << se puede leer, // esto lee varios fragmentos de código que pueden aparecer en una sola llamada
buffer = buffer || (esto << leído); // juntar los fragmentos
Espera (.01); // esto no es realmente necesario excepto para obtener los fragmentos en un solo registro
); // reúne todo lo que puedas
buffer = Regex (buffer, "\ s +", "", GLOBALREPLACE); // limpiar el búfer, eliminar CRs y LFs
Si (Recortar (búfer)! = "", // vea si tenemos algo que decir. hay espacios en blanco en la salida de PING
(datatab [miInstancia]) << addrow (1); // mi mesa recibe una nueva fila
(datatab [miInstancia]): texto = búfer; // almacenar el búfer limpiado
);
)
)
)
)
);
);
// si quieres, puedes esperar los programas de ejecución. Ellos * requieren * JMP estar inactivo para hacer
// la devolución de llamada a la función de lectura; el siguiente bucle de sondeo usa espera (.1) para asegurarse
// JMP es mayormente inactivo. Cuando el programa PING termina, cierra el identificador del archivo STDOUT
// JMP está escuchando, lo que hace que el mensaje isReadEof devuelva VERDADERO.
Para (iJOB = 1, iJOB <= NJOBS, iJOB ++,
While (! ((Runprog [iJOB]) << isReadEof), Wait (.1))
);
Escribe ("All Done! \! N"); // ahora puedes proceder con las tablas de datos
¡Muchas gracias!
Quizás sea obvio para aquellos que realmente usarían esto, pero en una Mac necesitarías:
Ejecutable( "/ sbin / ping" )
Opciones ({ "-c 10" , quien [iJOB]}),