Matlab : running a function in a COM server without blocking matlab?

匿名 (未验证) 提交于 2019-12-03 08:56:10

问题:

I'm working on Matlab 64-bits R2011b, and I have to use a 32-bits version (I have R2010b installed) to command a hardware (32-bit dll). For that, I created a COM server with actxserver() and it works.

However, whenever a function takes time in the 32-bit session, the 64-bit session becomes 'busy' and nothing works anymore until completion.

I simplified my problem in the script below : if you have two Matlab versions installed, you can try my code and see my problem.

In a few words :

  • one button starts a timer that simply shows the time elapsed since it was started
  • the other button makes a 2 seconds pause in the 64-bit session (no bad effect), followed by a 2 seconds pause in the 32-bit session (bad effect : the timer halts !).

Any advice would be appreciated to prevent blocking the 64-bit session.

NB : I have the parallel computing toolbox installed but never used it yet. The parfeval() function wasn't implemented in the R2011b Matlab version (in case it would have been useful).

function timer_test % handles ha=[]; % create COM server for Matlab 32 bits (change the version accordingly) ha.matlab32bits = actxserver('Matlab.Application.7.11'); % Create or actualize figure if already open-------------------------- alreadyOpenHandle=findall(0,'Name','TimerTest'); if isempty(alreadyOpenHandle)     ha.f=figure('Position',[400 400 200 140]...         ,'Name','TimerTest'...         ,'NumberTitle','Off'...         ,'MenuBar','none'...         ,'Color',[0.94 0.94 0.94] ...         ); else     ha_Old=guidata(alreadyOpenHandle);     ha.f=ha_Old.f;     figure(ha.f);                   % Bring figure to front     clf                             % Clear all graphics objects end  % Buttons------------------------------------------------------------- ha.button1=uicontrol('Style','Togglebutton' ...     ,'Position',[20 80 80 40] ...     ,'Parent',ha.f ...     ,'String','Run Timer' ...     ,'Callback',@button1_Callback ...     ); ha.button2=uicontrol('Style','Pushbutton' ...     ,'Position',[100 80 80 40] ...     ,'Parent',ha.f ...     ,'String','Pause' ...     ,'Callback',@button2_Callback ...     );  % Timer-------------------------------------------------------------- ha.myTimer = timer('ExecutionMode', 'fixedRate' ...      ,'Period', 0.1 ...     ,'TasksToExecute',1000 ...     ,'TimerFcn', {@myTimerFcn,ha.f} ... % Specify callback     );  % Text--------------------------------------------------------------- ha.text1=uicontrol('Style','Text' ...     ,'Position',[40 20 50 40] ...     ,'String','0 s' ...     ); ha.text2=uicontrol('Style','Text' ...     ,'Position',[120 20 50 40] ...     ,'String','-' ...     );  guidata(ha.f,ha);  %====================================================================  function button1_Callback(hO,ev) ha=guidata(findall(0,'Name','TimerTest')); if get(ha.button1,'Value')==1     start(ha.myTimer); else     stop(ha.myTimer); end   function button2_Callback(hO,ev) ha=guidata(findall(0,'Name','TimerTest')); % pause the 64-bit matlab (timer still running, ok) set(ha.text2,'String','Paused in 64bits'); pause(2); % pause the 32-bit matlab (timer halts !!) set(ha.text2,'String','Paused in 32bits'); drawnow; ha.matlab32bits.Execute('pause(2)'); % end set(ha.text2,'String','-');   function myTimerFcn(obj,ev,f) drawnow; ha=guidata(findall(0,'Name','TimerTest')); elapsed=[num2str(roundn(obj.TasksExecuted/10,-1),'%4.1f') ' s']; set(ha.text1,'string',elapsed);

回答1:

The combination of timer + pause is a (special) misleading case, and you should not expect the same non-blocking behavior from all operations.

After all, MATLAB is a single-threaded execution environment (rather the part which I refer to as the core engine/interpreter), even though it has many other background threads used for various purposes such as UI or I/O. Having a dedicated UI thread, think Java EDT, is important to keep the IDE responsive during long operations.

During a pause call, certain events continue to be processed (such as window repainting messages, HG callbacks, Java events), while the execution is halted. For this reason, it is not a perfect way to simulate heavy computation load.

As far as I know, MATLAB timers are implemented in Java, and these timer objects emit Java events of the kind that are listened-to and processed during a pause period. Thus your timer callback function was still being called, which in turn updates the GUI generating more HG events that are also permitted to execute during a pause...

Now if you replace the pause(2) of the "64-bit version" with a function call that actually consume active CPU time (say computing the eigenvalues of a huge matrix), you will notice that the timer callback is no longer being executed on the specified intervals.

From the point of view of the "64-bit MATLAB" process, the ha.matlab32bits.Execute call is of the same nature (a method invoked in a COM server) which will also block the execution thread.

In both cases, you could try to maximize the figure window such calls, and you will see that even window repaint message are not being promptly dispatched by the event loop, on account of the main thread being busy running those long operations.


Here is my version of the coded modified to show that both cases can block MATLAB execution (either local function called on the current MATLAB process or a remote function called on the other MATLAB process using COM automation):

function timer_test     % h is a handles structure shared with the nested functions     h = create_gui();     h.actx = actxserver('Matlab.Application.8.2');     h.timer = timer('ExecutionMode', 'fixedRate', 'Period',0.1, ...         'BusyMode','drop', 'TasksToExecute',1000, 'TimerFcn',@timer_cb);      function toggle_btn_cb(o,~)         % start/stop timer         if get(o, 'Value') == 1             start(h.timer);         else             stop(h.timer);             set(h.txt1, 'String','0'); drawnow         end     end      function run_btn_cb(~,~,mode)         set(h.btns, 'Enable','off')         if strcmp(mode,'local')             % local call             set(h.txt2, 'String','Locally'); drawnow             tic             eig(rand(2000));             toc         elseif strcmp(mode,'remote')             % remote call             set(h.txt2, 'String','Remotely'); drawnow             tic             %Feval(h.actx, 'pause', 0, 5);             Execute(h.actx, 'pause(5);');             toc         end         set(h.btns, 'Enable','on')          % reset text         set(h.txt2,'String',''); drawnow     end      function timer_cb(~,~)         % abort if figure was closed         if ~ishghandle(h.fig)             try stop(h.timer); delete(h.timer); end             return         end          % update counter         set(h.txt1, 'String',sprintf('%d', h.timer.TasksExecuted))         drawnow     end      function handles = create_gui()         % build the GUI         hfig = figure('Menu','none', 'Position',[400 400 275 140]);         uicontrol('Style','togglebutton', 'String','Start/Stop', ...             'Parent',hfig, 'Position',[20 80 80 40], ...             'Callback',@toggle_btn_cb);         hbtn1 = uicontrol('Style','pushbutton', 'String','Local Call', ...             'Parent',hfig, 'Position',[100 80 80 40], ...             'Callback',{@run_btn_cb,'local'}, 'Interruptible','on');         hbtn2 = uicontrol('Style','pushbutton', 'String','Remote Call', ...             'Parent',hfig, 'Position',[180 80 80 40], ...             'Callback',{@run_btn_cb,'remote'}, 'Interruptible','on');         htxt1 = uicontrol('Style','text', 'String','0', ...             'Parent',hfig, 'Position',[50 20 60 20]);         htxt2 = uicontrol('Style','text', 'String','', ...             'Parent',hfig, 'Position',[130 20 100 20]);         handles = struct('fig',hfig, 'btns',[hbtn1,hbtn2], ...             'txt1',htxt1, 'txt2',htxt2);     end  end



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!