如何在 .NET 中使用命令行 Matlab 而无需链接?
我终于发现了一种无需链接即可从 .NET 使用命令行 Matlab 的方法:
使用 David A. Zier 的“csmatio”dll 将变量从 .NET 写入 MAT 文件。
将从 Matlab 读取文件,对其进行处理并将结果保存到 MAT 文件中:
var process = new Process() { StartInfo = 新的 ProcessStartInfo() { 文件名 = Matlab 可执行文件名, 参数=“-nodisplay”+ “-nojvm”+ " -r \"一些命令; ” + “保存文件名输出变量;” + “出口;\”” } }; 进程.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(对象发送者, FileSystemEventArgs e) { 等待.Set(); }; foreach(Enumerable.Range(0, 2) 中的 var i) { if (!wait.WaitOne(毫秒超时)) { 抛出新的 TimeoutException(); } } 线程.睡眠(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();
I finally discovered a way to use command line Matlab from .NET without linking:
Write variables from .NET to a MAT file using David A. Zier's "csmatio" dll.
Read the file from Matlab, process it and save the results to a MAT file:
var process = new Process() { StartInfo = new ProcessStartInfo() { FileName = MatlabExecutableFileName, Arguments = "-nodisplay " + "-nojvm " + " -r \"somecommands; " + "save FILENAME OUTPUTVARIABLES; " + "exit;\"" } }; process.Start();
The worst part: Wait until the process finishes.
The naive approach:
process.WaitForExit();
Doesn't work because matlab spawns the main application in a new thread
Watching for the output file for changes is tricky:
new FileSystemWatcher(MatlabPath, fileName) .WaitForChanged(WatcherChangeTypes.All)
Was not working because of a bug on this class.
The currently working code is longer:
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); }
But I am concerned about the last line of code. The code block above was written with the intent of avoiding it, but I don't know what else to do. This amount of time will be too much on some computers and too little on others.
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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
更好的选择是 matlab 的
-wait
标志。 它告诉 matlab 启动程序与主 matlab 进程一起终止。A much better option is the
-wait
flag for matlab. It tells the matlab starter to terminate together with the main matlab process.不确定我是否完全理解这个问题(您本质上是在尝试检测 matlab 进程何时完成,对吗?),但是您找不到 matlab 的主要应用程序进程和应用程序吗? 等待它退出? 即这样的事情:
看起来这比尝试观看它更改文件和更改文件更简单。 猜猜什么时候完成...
Not sure if I completely understand the question (you're essentially trying to detect when the matlab process finishes right?), but couldn't you find matlab's main application process & wait for it to exit? i.e. something like this:
Seems like that would be simpler than trying to watch it change files & guess when its finished...
如何确定单独线程的实际进程并对其调用
WaitForExit
? 也许可以使用命令行程序tasklist
来获取所有 MATLAB 进程的 PID,并过滤掉您拥有的进程的 PID。或者,可能有一个 .NET 结构(可能与
process
相关),它可以返回process
的子线程并等待它。不幸的是,我不知道细节,但值得尝试搜索该途径。
How about determining the actual process for the separate thread and calling
WaitForExit
on it? Maybe use the command line programtasklist
to get the PID's of all MATLAB processes and filter out the PID of the one you have.Alternatively, there might be a .NET structure (probably related to
process
) which could return a child thread ofprocess
and wait for it.Unfortunately, I don't know details, but it's worth a try searching that avenue.
我稍微改变了解决方案,所以它对我有用
I slightly changed the Solution so it worked for me