如何干净地停止运行 matlab dll 函数的 .NET 线程

Posted

技术标签:

【中文标题】如何干净地停止运行 matlab dll 函数的 .NET 线程【英文标题】:How to cleanly stop a .NET thread that is running a matlab dll function 【发布时间】:2017-12-12 21:55:21 【问题描述】:

我用这个函数编译了一个带有命名空间 flagTest 和类名 test 的 Matlab DLL:

function [ ] = flagTest( flag )
    while flag
        disp(flag);
        pause(1);
    end
end

我可以像这样在 c# 中调用这个 dll 函数:

using MathWorks.MATLAB.NET.Arrays;
using MathWorks.MATLAB.NET.Utility;
namespace ConsoleApplication1

    class Program
    
        static void Main(string[] args)
        
            //create test class object
            flagTest.test T = new flagTest.test();
            MWLogicalArray flag = new MWLogicalArray(true);
            //call matlab function flagTest
            T.flagTest(flag);
        
    

很抱歉,由于我将命名空间和函数都称为flagTest,因此造成任何混淆。

我现在要做的是将这个T.flagTest(flag) 函数调用放在一个线程上(我知道该怎么做),并在用户单击UI 上的按钮时将flag 的值更改为false停止线程。在我们应用程序中真正的 matlab 函数中,我需要做一些工作,例如完成当前文件的读取并将内存中的数据写入磁盘,然后才能停止函数线程。我不能在 matlab 函数中不做任何事情就停止线程。

我想知道是否有任何方法可以实现此功能,因为我无法弄清楚如何通过引用将对象从 .NET 传递到 Matlab。

【问题讨论】:

【参考方案1】:

为什么不将控制循环的标志封装到test 类中?例如:

classdef test < handle
    properties (Access = private)
        Running
    end

    methods
        function Start(this)
            if (this.Running)
                disp('Already Running');
                return;
            end

            this.Running = true;
            disp('Started');

            while (this.Running)
                pause(1);
                disp('Running');
            end

            disp('Stopped');
        end

        function Stop(this)
            this.Running = false;
        end
    end
enn

然后,在您的 C# 程序集中:

namespace ConsoleApplication1

    public static class Program
    
        public static void Main(String[] args)
        
            flagTest.test T = new flagTest.test();
            T.Start();

            while (true)
            
                String command = Console.ReadLine();

                if (command.ToLowerInvariant() == "stop")
                
                    T.Stop();
                    break;
                
            
        
    

话虽如此,这种方法与多线程无关。如果你想使用多线程,你必须考虑三个重要的事情:

    如何在线程被杀死时保存您的工作人员进度 如何实现取消信号属性 如何控制取消信号

这只是一个例子,但必须改进:

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

List<Thread> threads = new List<Thread>();

for (Int32 i = 0; i < 5; ++i)

    flagTest.test T = new flagTest.test();
    token.Register(() => T.Stop());

    Thread thread = new Thread(() => T.Start());
    thread.IsBackground = true;

    threads.Add(thread);

    thread.Start();

然后,当用户要求取消时,只需调用:

cts.Cancel();
cts.Dispose();

【讨论】:

托马索,非常感谢您的帮助!但是,我无法弄清楚如何将此类编译为 .NET dll,因为我们似乎只能使用 matlab deploytool 编译独立函数。我阅读了this,但仍然没有 100% 理解它是如何工作的,因为该链接中的示例不会直接在 C++ 代码中生成GlobalData 类,因此我们不能使用该类并调用该类中的另一个方法。跨度> 我正在考虑一个替代方案:将所有循环带到 Matlab 之外,并将它们放入 .NET 程序集中。然后,编写您的 Matlab 函数,以便它可以处理具有确定偏移量的数据,如果可能的话,例如 DoWork(from,to)。至此,您将能够完全控制您的线程,因为它们是单面的。 是的。这将是我想到的另一种选择,需要大量将 Matlab 代码重写为 c#,我的队友决定不使用它......我能够将 matlab 函数包装在一个matlab 类并将该函数编译为 dll 并从 c# 调用它。但是,我面临的问题是我不知道如何将 matlab 类转换为 MWArray 对象,因此我可以更改类中的 flag 属性。我认为这将是我在这里提出的另一个问题。再次非常感谢您。 虽然我确信有一种方法可以使用对象实例,但这个答案提供了另一种解决方案:***.com/questions/8841146/…

以上是关于如何干净地停止运行 matlab dll 函数的 .NET 线程的主要内容,如果未能解决你的问题,请参考以下文章

如何查看从 Matlab 中 Mex 函数使用的 DLL 调用的 printf 的输出?

C#&MatLab:我是不是需要 MCR 才能在任何计算机上运行 MWArray.dll?

使用 Matlab 运行时无法找到 mclmcrrt*.dll

如何将文件路径从 asp.net matlab ne builder dll 工具传递给 Matlab 函数

如何在Matlab中停止正在运行的脚本[重复]

如何让matlab全速运行