Matlab-GUI warning when using parfeval(): "Unable to save App Designer app object."

1.1k Views Asked by At

I am trying to call parallel functions within my Matlab-GUI by pushing a startbutton.

For the beginning I tried to call one single function ("ReadTwinCAT") but I'm always getting the following error-message:

"Warning: Unable to save App Designer app object. Save not supported for matlab.apps.AppBase objects."

As I thought I already used parallel functions like this within a GUI, I don't know what I am doing wrong...

Matlab-App-Designer Code:

properties (Access = private)
    running_state = 0; % Description
    tcClient;
    db_conn;
end

methods (Access = private)

    function ReadTwinCAT(app)

        while app.running_state == 1
            disp('running')
            pause(0.1) 
        end  
        disp('stopped')

    end         
end


% Callbacks that handle component events
methods (Access = private)

    function StartButtonPushed(app, event)

       app.running_state = 1;

       pool = gcp(); %Initialize pool of workers

       parfeval(pool, @ReadTwinCAT, 0, app); %Call parallel function

    end
end
1

There are 1 best solutions below

0
Brionius On

Ok, I think I found an answer from Mathworks staff: https://www.mathworks.com/matlabcentral/answers/366576-will-there-be-a-support-of-the-parallel-toolbox-in-matlab-app-designer#comment_720548

Note the limitation of accessing the app object inside the parfor loop or any other functions called though Parallel Computing Toolbox.

If you need to access properties of your app pass them down as values directly, e.g. instead of

b = [0,0];  
parfor i=1:2
    b(i) = app.myprop*2
end

use

tmp = app.myprop;
b = [0,0];  
parfor i=1:2
    b(i) = tmp*2
end

So it seems that you can't access (or it would seem set) the properties of the app object within a parallelized function. If you want to get data out, you'll probably have to set up a communication system using parallel.pool.DataQueue. Your example is tough to parallelize. A better option would probably be to add a listener to your running_state property, and/or use a timer function.

The major downside of this is that the function you call from the timer is not actually parallelized - it runs in the same thread, so if you have a lot of computation in ReadTwinCAT, I think it will cause lag/unresponsiveness in the GUI.

I've modified your code to use a timer instead of parfeval:

properties (Access = private)
    running_state = 0; % Description
    runningTimer;
    tcClient;
    db_conn;
end

methods (Access = private)

    function ReadTwinCAT(app, varargin)
        if app.running_state == 1
            disp('running')
        else
            stop(app.runningTimer);
            disp('stopped')
        end
    end

end

% Callbacks that handle component events
methods (Access = private)

    function StartButtonPushed(app, event)
        app.running_state = 1;

        app.runningTimer = timer;
        app.runningTimer.Period = 0.1;
        app.runningTimer.ExecutionMode = 'fixedRate';
        app.runningTimer.TimerFcn = @app.ReadTwinCAT;
        start(app.runningTimer)
    end

end