1

我终于发现了一种无需链接即可从 .NET 使用命令行 Matlab 的方法:

  1. 使用 David A. Zier 的“csmatio”dll 将变量从 .NET 写入 MAT 文件。

  2. 从 Matlab 读取文件,对其进行处理并将结果保存到 MAT 文件中:

    var process = new Process()
    {
        StartInfo = new ProcessStartInfo()
        {
            FileName = MatlabExecutableFileName,
            Arguments = "-nodisplay " + 
               "-nojvm " +
               " -r \"somecommands; " + 
               "save FILENAME OUTPUTVARIABLES; " +
               "exit;\""
        }
    };
    process.Start();
    
  3. 最糟糕的部分:等到过程完成。

    天真的方法:

    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();
4

4 回答 4

3

一个更好的选择是-waitmatlab 的标志。它告诉 matlab 启动程序与主 matlab 进程一起终止。

于 2013-01-27T16:51:52.857 回答
1

不确定我是否完全理解了这个问题(您实际上是在尝试检测 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();

似乎这比尝试观看它更改文件并猜测它何时完成更简单......

于 2009-07-21T02:19:28.387 回答
0

如何确定单独线程的实际进程并调用WaitForExit它?也许使用命令行程序tasklist来获取所有 MATLAB 进程的 PID 并过滤掉你拥有的那个进程的 PID。

或者,可能有一个 .NET 结构(可能与 相关process),它可以返回一个子线程process并等待它。

不幸的是,我不知道细节,但值得一试寻找这条途径。

于 2009-07-23T22:11:02.823 回答
0

我稍微改变了解决方案,所以它对我有用

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();
于 2012-11-07T14:02:53.940 回答