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)
并正确打印“正在运行”,但随后它停在那里并等待计时器完成。更令人困惑的是,如果我将 1 秒的暂停时间更改为 0.9 秒,计时器会立即停止并显示以下输出:
跑步
试图阻止
现在应该停止
我知道 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
要查看它的实际效果:
推荐阅读
- objective-c - 目标 C 多行 UILabel 不起作用
- python - 如何使用 matplotlib 创建条状图表?
- lodash - 无法使用 lodash | 过滤 nuxt
- python - SQLAlchemy:如何扩展混合属性?
- javascript - 拒绝在框架中显示“链接”
- java - JavaFX 表列排序 - 当单元格没有值时使用其他列的值?
- apache-spark - 写入配置单元分区时,Spark 暂存目录竞争条件?
- python - 在 Python 中查找数据框日期列和参考日期之间的时间
- java - 使用springboot rest客户端发送多部分请求总是给出400 BAD_REQUEST错误
- javascript - 我们可以合并覆盖报告 Jest 和 Mocha 吗?