2009-07-12 7 views
1

J'ai finalement découvert un moyen d'utiliser la ligne de commande Matlab de .NET sans lien avec:Comment utiliser la ligne de commande Matlab depuis .NET sans lien?

  1. variables Write de .NET dans un fichier MAT en utilisant dll "de csmatio" de David A. Zier.

  2. Lire le fichier de Matlab, processus et enregistrer les résultats dans un fichier MAT:

    var process = new Process() 
    { 
        StartInfo = new ProcessStartInfo() 
        { 
         FileName = MatlabExecutableFileName, 
         Arguments = "-nodisplay " + 
          "-nojvm " + 
          " -r \"somecommands; " + 
          "save FILENAME OUTPUTVARIABLES; " + 
          "exit;\"" 
        } 
    }; 
    process.Start(); 
    
  3. Le pire: Attendez jusqu'à ce que le processus se termine.

    L'approche naïve:

    process.WaitForExit(); 
    

    ne fonctionne pas parce que Matlab engendre l'application principale dans un nouveau thread

    Regarder le fichier de sortie des changements est délicat:

    new FileSystemWatcher(MatlabPath, fileName) 
        .WaitForChanged(WatcherChangeTypes.All) 
    

    Ne travaillait pas à cause d'un bug sur cette classe.

    Le code travaille actuellement est plus:

    using (var watcher = new FileSystemWatcher(MatlabPath, fileName)) 
    { 
        var wait = new EventWaitHandle(false, EventResetMode.AutoReset); 
        watcher.EnableRaisingEvents = true; 
        watcher.Changed += delegate(object sender, FileSystemEventArgs e) 
        { 
         wait.Set(); 
        }; 
        foreach(var i in Enumerable.Range(0, 2)) 
        { 
         if (!wait.WaitOne(MillissecondsTimeout)) 
         { 
          throw new TimeoutException(); 
         } 
        } 
        Thread.Sleep(1000); 
    } 
    

    Mais je suis préoccupé par la dernière ligne de code. Le bloc de code ci-dessus a été écrit avec l'intention de l'éviter, mais je ne sais pas quoi faire d'autre. Cette quantité de temps sera trop sur certains ordinateurs et trop peu sur d'autres.

SOLUTION

var previousProcesses = Process 
    .GetProcessesByName("Matlab") 
    .Select(a => a.Id) 
    .ToArray(); 
process.Start(); 
process.WaitForExit(); 
var currentProcess = Process 
    .GetProcessesByName("Matlab") 
    .Where(a => !previousProcesses.Contains(a.Id)) 
    .First(); 
currentProcess.WaitForExit(); 

Répondre

3

Une option beaucoup mieux est le drapeau -wait pour Matlab.Il indique au démarreur matlab de se terminer avec le processus matlab principal.

1

Je ne sais pas si je comprends complètement la question (vous êtes essentiellement essayer de détecter le moment où le processus de Matlab se termine à droite?), Mais pas pu vous trouver principale de Matlab processus de demande & l'attendre pour sortir? à-dire quelque chose comme ceci:

process.WaitForExit(); //only waits for the launcher process to finish 
//but now matlab should be running in a new process... 
var matlabProcess = Process.GetProcessesByName("whatever process is called"); 
//assuming only one matlab instance running... 
//you'd probably want to write some defensive code here... 
matlabProcess[0].WaitForExit(); 

On dirait qui serait plus simple que d'essayer de regarder changer des fichiers & deviner quand son fini ...

+0

Parfait! Ça a marché! –

0

Que diriez-vous de déterminer le processus réel du thread séparé et appelant WaitForExit dessus? Peut-être utiliser le programme de ligne de commande tasklist pour obtenir les PID de tous les processus MATLAB et filtrer le PID de celui que vous avez.

Alternativement, il pourrait y avoir une structure .NET (probablement liée à process) qui pourrait renvoyer un thread enfant de process et l'attendre. Malheureusement, je ne connais pas les détails, mais ça vaut le coup d'essayer de chercher cette avenue.

0

je légèrement changé la solution il a fonctionné pour moi

var previousProcesses = Process 
    .GetProcessesByName("Matlab") 
    .Select(a => a.Id) 
    .ToArray(); 
var process = Process.Start(startInfo); 
process.WaitForExit(); 
var newProcessRunning = Process 
    .GetProcessesByName("Matlab") 
    .Where(a => !previousProcesses.Contains(a.Id)); 
if (newProcessRunning.Count() != 0) 
    newProcessRunning.First().WaitForExit(); 
Questions connexes