matlab - 从回调中停止 Matlab 计时器(在外部输入/事件之后)

标签 matlab

我正在计时器回调中运行长数据预加载,并且我希望能够通过外部输入(例如,单击 GUI 按钮)中途停止回调。 stop() 函数将停止计时器调用,但不会停止回调函数本身。

这是一个简单的例子:

timerh = timer('TimerFcn' , @TimerCallback,'StartDelay' , 1, 'ExecutionMode' , 'singleShot');
NeedStopping = false;

start(timerh)

disp('Running')
pause(1)
disp('Trying to stop')
NeedStopping = true;


function TimerCallback(obj, event)
% Background data loading in here code in here; in this example, 
% the callback simply displays numbers from 1 to 100

    for k = 1 : 100
        drawnow();  % Should allow Matlab to do other stuff
        NeedStopping = evalin('base' , 'NeedStopping');
        if NeedStopping
            disp('Should stop now')
            return
        end
        disp(k)
        pause(0.1)
    end
end

我希望此脚本显示 1 到(大约)10 之间的数字,但计时器回调直到 100 才会停止。 奇怪的是,代码到达了 pause(1) 之前的行并正确打印了“Running”,但随后它停在那里并等待计时器完成。 更令人困惑的是,如果我将 1 秒暂停更改为 0.9 秒,计时器会立即停止并显示以下输出:

Running

Trying to stop

Should stop now

我知道 Matlab 大部分是单线程的,但我认为 drawnow() 函数应该允许它处理其他东西。


编辑:我的问题背后的具体用途: 我有一个带有“下一个”按钮的 GUI,可以加载多个图像并并排显示它们。图片较大,加载需要时间;因此,当用户查看图片时,我想预加载下一组。这可以通过计时器在后台完成,并且有效。 但是,如果用户在预加载完成之前单击“下一步”,我需要停止它,显示当前图像,并启动下一步的预加载。因此,定时器需要在回调执行期间停止。

最佳答案

这是如何设置可中断 callback 的演示。根据您的示例的设置方式,我没有看到需要实际的计时器,因此我将其作为标准按钮回调。

注意:如果您决心将其用于计时器,您可以使用完全相同的解决方案,只需分配 startProcess回调到计时器而不是 gui 按钮。

function h = interuptible_callback_demo

% generate basic gui with 2 buttons
h = create_gui ;
guidata( h.fig , h )

% create application data which will be used to interrupt the process
setappdata( h.fig , 'keepRunning' , true )

end


function startProcess(hobj,~)
    h = guidata( hobj ) ;
    % set the 'keepRunning' flag
    setappdata( h.fig , 'keepRunning' , true )
    % toggle the button states
    h.btnStart.Enable = 'off' ;
    h.btnStop.Enable  = 'on' ;

    nGrainOfSand = 1e6 ;
    for k=1:nGrainOfSand
        % first check if we have to keep running
        keepRunning = getappdata( h.fig , 'keepRunning' ) ;

        if keepRunning
            % This is where you do your lenghty stuff
            % we'll count grains of sand for this demo ...
            h.lbl.String = sprintf('Counting grains of sands: %d/%d',k,nGrainOfSand) ;
            pause(0.1) ;
        else
            % tidy up then bail out (=stop the callback)
            h.lbl.String = sprintf('Counting interrupted at: %d/%d',k,nGrainOfSand) ;
            % toggle the button states
            h.btnStart.Enable = 'on' ;
            h.btnStop.Enable = 'off' ;
            return
        end
    end
end

function stopProcess(hobj,~)
    h = guidata( hobj ) ;
    % modify the 'keepRunning' flag
    setappdata( h.fig , 'keepRunning' , false )
end

function h = create_gui
    h.fig = figure('units','pixel','Position',[200 200 350 200]) ;
    h.btnStart = uicontrol('style','pushbutton','string','Start process',...
                            'units','pixel','Position',[50 100 100 50],...
                            'Callback',@startProcess) ;
    h.btnStop  = uicontrol('style','pushbutton','string','Stop process',...
                            'units','pixel','Position',[200 100 100 50],...
                            'Callback',@stopProcess,'enable','off') ;
    h.lbl  = uicontrol('style','text','string','','units','pixel','Position',[50 20 200 50]) ;
end

要查看它的实际效果:

enter image description here

关于matlab - 从回调中停止 Matlab 计时器(在外部输入/事件之后),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55724104/

相关文章:

MATLAB:将 LaTeX 字符与轴标题中的数据格式相结合

excel - 在 MATLAB 中使用贝塞尔函数

matlab - 如何对当前像素的 8 个相邻像素值求和。

matlab - 无法设置Matlab类的参数

MATLAB 文本框位于旋转 3D 图顶部的恒定位置?

Matlab:用3个向量制作等高线图

matlab - 获取圆边界

python - Matlab 中的高效矩阵乘法

matlab - matlab theta1中实现的梯度下降搜索不正确

c++ - 在 MEX C++ 中从 std::vector 创建 MATLAB 数组