mise à jour 27apr2018: mise en forme de réparation
Je viens de poser une question sur l’utilisation simultanée de plusieurs instances de RunProgram. Voici un exemple qui exécute trois copies de PING sur trois adresses IP différentes et enregistre les résultats dans trois tables de données différentes. L'exemple montre comment utiliser la valeur "paramètre" pour que chaque RunProgram sache quelle table de données utiliser. La pièce jointe est identique au code en ligne ...
// 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

Il y a une limite au nombre de ceux-ci que vous pouvez exécuter en même temps. Probablement pas des centaines; ils utilisent sur votre ordinateur des ressources non illimitées.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />Dans JMP 11, vous pouvez modifier le script pour utiliser des fonctions ReadFunctions uniques pour chaque instance RunProgram. Cet exemple incorpore la variable "myInstance" dans la liste des variables locales, avec une affectation résolue par Eval (EvalExpr (... expr () ... mécanisme.
(Désactivez l'option Traduire en haut de l'écran si le texte ci-dessous est en désordre.)
// d'abord, nous aurons besoin de conteneurs pouvant être indexés de 1 à NJOBS
// et conserve les références aux tables de données et aux RunPrograms.
datatab = tableau associatif ();
runprog = tableau associatif ();
who = {"jmp.com", "google.com", "bing.com"}; // chaque runProgram peut faire quelque chose de différent
NJOBS = N Items (who);
// next, une boucle pour faire des tables et lancer les RunPrograms
Pour (iJOB = 1, iJOB <= NJOBS, iJOB ++,
// crée un tableau avec une colonne de texte, puis agrandit la colonne de manière à pouvoir afficher plus de données
datatab [iJOB] = Nouvelle table (who [iJOB], addrows (1), nouvelle colonne ("text", Caractère, Valeurs définies ({"pinging ..."})));
datatab [iJOB]: text << setdisplaywidth (500);
// lance le RunProgram. Il est particulièrement important de s’assurer que le RunProgram
// objet est stocké dans une variable qui ne sera pas écrasée ... le tableau associatif le contient.
runprog [iJOB] = Eval (
Eval Expr (
Exécuter de programme(
Exécutable ("PING.EXE"), // ceci est le "travail" dont nous lançons plusieurs copies, en parallèle
Options ({"-n 10", Expr (who [iJOB])}) // // exécutées pendant 10 secondes --- il s'agit d'une option PING
// pas dans JMP 11: Parameter (iJOB), // mémoriser quelle "instance" il s'agit --- ceci va à la ReadFunction
ReadFunction (// définit une fonction qui sera appelée pour beaucoup de petits extraits de texte
Fonction ({this / * pas dans JMP 11:, myInstance * /}, // myInstance est l'iJOB
{tampon = "",
// la façon JMP 11 ...
myInstance = Expr (iJOB) // evalexpr s'en occupe
}, // local pour cette instance. mettre en mémoire tampon de petits extraits
While (this << canread, // ceci lit plusieurs extraits qui peuvent apparaître dans un seul appel
tampon = tampon || (ceci << lu); // rassemble les extraits
Attendre (0,01); // ce n'est pas vraiment nécessaire, sauf pour obtenir les extraits dans un seul enregistrement
) // rassembler autant que possible
tampon = regex (tampon, "\ s +", "", GLOBALREPLACE); // nettoie le tampon, supprime les CR et les LF
If (Trim (buffer)! = "", // vérifie si nous avons quelque chose à dire. il y a des blancs dans la sortie de PING
(datatab [myInstance]) << addrow (1); // ma table a une nouvelle ligne
(datatab [myInstance]): text = buffer; // stocke le tampon nettoyé
)
)
)
)
)
)
)
// si vous le souhaitez, vous pouvez attendre les programmes d'exécution. Ils * exigent que * JMP soit inactif pour pouvoir
// le rappel à la fonction de lecture; la boucle d’interrogation suivante utilise wait (.1) pour s’assurer que
// JMP est principalement inactif. Lorsque le programme PING se termine, il ferme le descripteur de fichier STDOUT
// JMP écoute, ce qui fait que le message isReadEof renvoie VRAI.
Pour (iJOB = 1, iJOB <= NJOBS, iJOB ++,
While (! ((Runprog [iJOB]) << isReadEof), attendez (.1))
)
Write ("All Done! \! N"); // maintenant vous pouvez continuer avec les tables de données
Merci beaucoup!
Peut-être évident pour ceux qui l'utilisent, mais sur un Mac, il vous faut:
Exécutable ( "/ sbin / ping" ),
Options ({ "-c 10" , qui [iJOB]}),