Matlab onCleanup函数未执行 [英] Matlab onCleanup function not executed

查看:237
本文介绍了Matlab onCleanup函数未执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MATLAB R2013a中遇到了以下问题,由于某种原因,我不明白在一个函数中定义了计时器(包括TimerFcn)时没有调用onCleanup函数.

I ran into the following issue in MATLAB R2013a, which for some reason I do not understand does not call the onCleanup function when in a function a timer (including a TimerFcn) is defined.

我添加了两个显示问题的最小示例:

I add two minimal examples showing the problem:

首先是按预期方式调用清理例程的工作版本:

first the working version where the cleanup routine is called as expected:

function mytest(time)
  t = timer();
  myclean = onCleanup(@() disp('function ended'));
  pause(time);
end

现在是没有调用清理的越野车版本(函数正常结束或按ctrl + c时都没有)

and now the buggy version in which the cleanup is not called (neither when the function ends normally or when ctrl+c is pressed)

function mytest2(time)
  t = timer();
  t.TimerFcn = @(o,s)disp(' ... waiting for some time'); 
  myclean = onCleanup(@() disp('function ends'));
  pause(time);
end

我在文档中找不到任何提示,为什么计时器或更具体的TimerFcn定义会更改清除代码的执行?

I could not find any hints in documentation why the timer or more specific the definition of the TimerFcn would change the execution of the cleanup code?

推荐答案

糟糕-这太讨厌了.它不是错误,但不是您期望从文档中获得的,也不是您想要的.幸运的是,它很容易解决.

Ouch - this is nasty. It's not a bug, but it's certainly not what you'd expect from the documentation, and it's not what you'd want. Fortunately it's pretty easy to work around.

首先,这是怎么回事?

好吧,onCleanup返回一个onCleanup对象.这是一个唯一目的是将析构函数方法设置为@() disp('function ends')的对象.当对象超出范围时(您希望该对象位于函数mytest2的末尾),它将被删除,其析构方法将执行,并显示您的消息.我想这就是您的期望.

Well, onCleanup returns you an onCleanup object. This is an object whose sole purpose is to have a destructor method that is set to your @() disp('function ends'). When the object goes out of scope (which you would expect to be at the end of the function mytest2), it gets deleted, its destructor method executes, and your message gets displayed. That's what you expect, I think.

但是,当您创建匿名函数@(o,s)disp(' ... waiting for some time')并将其分配给计时器的TimerFcn时,它将获取函数mytest2的整个当前工作空间的副本,包括onCleanup对象.计时器在基本工作区(不是函数工作区)中创建,并且甚至在函数末尾与onCleanup对象一起存在,后者永远不会超出范围,永远不会被删除,它的析构函数永远不会运行,并且您不会收到消息.

But when you create the anonymous function @(o,s)disp(' ... waiting for some time'), and assign it to the TimerFcn of your timer, it takes a copy of the entire current workspace of the function mytest2, including the onCleanup object. The timer is created in the base workspace (not the function workspace), and remains in existence even at the end of the function, along with the onCleanup object, which then never goes out of scope, never gets deleted, its destructor function never runs, and you don't get your message.

请注意:

  1. 如果您在基本工作区中运行a = timerfindall; delete(a);,则会收到消息,因为您已明确删除了计时器和onCleanup对象.
  2. 关于匿名函数复制整个工作区的这种行为已得到充分记录,尽管您可能不知道,并且您显然不希望它在此处那样工作.真讨厌.
  1. If you run a = timerfindall; delete(a); in the base workspace, you will get your message, as you've explicitly deleted the timer along with the onCleanup object.
  2. This behaviour about anonymous functions taking a copy of their entire workspace is fully documented, although you may not be aware of it, and although you clearly don't want it to work like that here. It's nasty.

幸运的是,它很容易解决:

Fortunately, it's easy to work around:

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

现在,当创建匿名函数时,它仅获取其 local 工作区的副本(即来自子函数setTimerFcn),该工作区不包含onCleanup对象. onCleanup对象超出了您的预期范围,一切都很好.

Now, when the anonymous function is created it only takes a copy of its local workspace (i.e. from the subfunction setTimerFcn), which does not include the onCleanup object. The onCleanup object goes out of scope at the point you expect it to, and everything's fine.

希望有帮助!

这篇关于Matlab onCleanup函数未执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆