我在MATLAB R2013a中遇到了以下问题,由于某些原因我不明白在函数中定义了一个定时器(包括TimerFcn)时没有调用onCleanup函数.
我添加了两个显示问题的最小示例:
首先是按预期调用清理例程的工作版本:
function mytest(time)
t = timer();
myclean = onCleanup(@() disp('function ended'));
pause(time);
end
Run Code Online (Sandbox Code Playgroud)
现在是没有调用清理的错误版本(当函数正常结束或按下ctrl + c时)
function mytest2(time)
t = timer();
t.TimerFcn = @(o,s)disp(' ... waiting for some time');
myclean = onCleanup(@() disp('function ends'));
pause(time);
end
Run Code Online (Sandbox Code Playgroud)
我在文档中找不到任何提示,为什么定时器或更具体的TimerFcn定义会改变清理代码的执行?
哎哟 - 这很讨厌.这不是一个错误,但它肯定不是你对文档的期望,它不是你想要的.幸运的是,它很容易解决.
首先,发生了什么?
好吧,onCleanup返回一个onCleanup对象.这是一个对象,其唯一目的是为您设置一个析构函数方法@() disp('function ends').当对象超出范围(您希望在函数末尾mytest2)时,它将被删除,执行析构函数方法,并显示您的消息.我想这就是你所期望的.
但是当您创建匿名函数@(o,s)disp(' ... waiting for some time')并将其分配给TimerFcn计时器时,它会获取函数的整个当前工作空间的副本mytest2,包括onCleanup对象.计时器是在基础工作区(而不是函数工作区)中创建的,并且即使在函数结束时仍然存在,并且onCleanup对象随后永远不会超出范围,永远不会被删除,它的析构函数永远不会运行,而且你没有收到你的消息.
注意:
a = timerfindall; delete(a);在基础工作区中运行,您将收到消息,因为您已明确删除计时器以及onCleanup对象.幸运的是,它很容易解决:
function mytest3(time)
t = timer();
setTimerFcn(t)
myclean = onCleanup(@() disp('function ends'));
pause(time);
end
function setTimerFcn(t)
t.TimerFcn = @(o,s)disp(' ... waiting for some time');
end
Run Code Online (Sandbox Code Playgroud)
现在,当创建匿名函数时,它只获取其本地工作空间(即来自子函数setTimerFcn)的副本,该副本不包括该onCleanup对象.该onCleanup对象超出范围在你期望的点,一切都很好.
希望有所帮助!