Как использовать командную строку Matlab из .NET без привязки?
Наконец-то я нашел способ использовать командную строку Matlab из .NET без ссылки:
Записывать переменные из .NET в MAT файл с использованием dll dll dll csmatio Дэвида А. Зиера.
Прочитайте файл из Matlab, обработайте его и сохраните результаты в файле MAT:
var process = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = MatlabExecutableFileName,
Arguments = "-nodisplay " +
"-nojvm " +
" -r \"somecommands; " +
"save FILENAME OUTPUTVARIABLES; " +
"exit;\""
}
};
process.Start();
Худшая часть: Подождите, пока процесс завершится.
Наивный подход:
process.WaitForExit();
Не работает, потому что matlab запускает основное приложение в новом потоке
Наблюдение за выходным файлом для изменений сложнее:
new FileSystemWatcher(MatlabPath, fileName)
.WaitForChanged(WatcherChangeTypes.All)
Не работает из-за ошибки в этом классе.
В настоящее время рабочий код длиннее:
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);
}
Но меня беспокоит последняя строка кода. Блок кода выше был написан с намерением избежать его, но я не знаю, что еще делать. Это количество времени будет слишком много на некоторых компьютерах и слишком мало на других.
Решение
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();
Гораздо лучшим вариантом является флаг -wait
для matlab. Он сообщает, что стартер Matlab заканчивается вместе с основным процессом matlab.
Не уверен, что я полностью понимаю вопрос (вы, по сути, пытаетесь обнаружить, когда процесс Matlab заканчивается правильно?), но не могли бы вы найти основной процесс приложения matlab и дождаться его выхода? то есть примерно так:
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();
Похоже, это было бы проще, чем пытаться посмотреть, как он меняет файлы и угадывает, когда закончится...
Я немного изменил решение, чтобы он работал у меня
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();
Как насчет определения фактического процесса для отдельного потока и вызова WaitForExit
на нем? Возможно, используйте программу командной строки tasklist
, чтобы получить PID всех процессов MATLAB и отфильтровать PID того, который у вас есть.
В качестве альтернативы может существовать структура .NET(возможно, связанная с process
), которая может возвращать дочерний поток process
и ждать его.
К сожалению, я не знаю деталей, но стоит попробовать найти этот проспект.
- Вопросы
- Filesystemwatcher
- Как использовать командную строку Matlab из .NET без привязки?