如何在 .NET 中使用命令行 Matlab 而无需链接?

发布于 2024-07-26 06:26:22 字数 1826 浏览 6 评论 0原文

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

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

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

    var process = new Process() 
      { 
          StartInfo = 新的 ProcessStartInfo() 
          { 
              文件名 = Matlab 可执行文件名, 
              参数=“-nodisplay”+  
                 “-nojvm”+ 
                 " -r \"一些命令;   ” +  
                 “保存文件名输出变量;” + 
                 “出口;\”” 
          } 
      }; 
      进程.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(对象发送者, 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:

  1. Write variables from .NET to a MAT file using David A. Zier's "csmatio" dll.

  2. 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();
    
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱的故事 2024-08-02 06:26:22

更好的选择是 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.

一百个冬季 2024-08-02 06:26:22

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

看起来这比尝试观看它更改文件和更改文件更简单。 猜猜什么时候完成...

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:

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

Seems like that would be simpler than trying to watch it change files & guess when its finished...

心在旅行 2024-08-02 06:26:22

如何确定单独线程的实际进程并对其调用 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 program tasklist 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 of process and wait for it.

Unfortunately, I don't know details, but it's worth a try searching that avenue.

草莓味的萝莉 2024-08-02 06:26:22

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

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

I slightly changed the Solution so it worked for me

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文