如何将数据传递给MATLAB oncleanup函数?

时间:2014-04-24 09:51:42

标签: matlab exception-handling

我有一个编译的matlab程序,可以自动调整机器参数。在调整周期结束时,我需要重新设置一些原始设置。有时出现意外错误,有时用户可以看到调优算法不能正常工作,因此应终止(使用control-C)。

如果发生可预测的错误,我可以使用try catch块恢复参数。但是,如果发生意外错误或用户调用control-C,程序将退出而不通过catch子句,并且机器处于未定义状态。

我知道我可以注册一个清理函数,该函数将在我的工作函数完成时运行,通常是通过可预测或不可预测的错误或control-C事件。理想情况下,如果发生可预测的错误,清理功能将无效并将控制权传递给顶层以进行清理。如果发生control-C事件或不可预测的错误,清理功能应警告用户程序失败,以便他们手动清理。

为此,我需要在运行时使清除功能已知预测或未预测终止(即控制-C)的事实。我知道清理函数在注册时会获取参数值的副本,并且这些参数值在运行时无法更改,因此传入参数不起作用。我认为应该工作的是将清理函数嵌套在我的工作函数中,以便封闭函数中的局部变量可用于清理函数。然而,这不起作用。

我的问题是:任何人都可以看到一种方法,只需一个布尔可用于一个干净的函数,这样它就可以在正常清理和异常清理之间进行选择吗?

以下是一些我认为应该有用的示例代码。

function do_tuning
  % Set this false to cause a warning messages for control-C or MATLAB coding errors.
  normalTermination = false;
  oc = onCleanup(@() my_clean_up());
  tuningError = tuning_function()   
  if tuningError
    % Set this true to suppress the warning message if a predictable error occurs.
    normalTermination = true;
    error('tuningError')
  end
  % Set this true to suppress the warning message if the function runs to completion.
  normalTermination = true;

  function my_clean_up
    if ~normalTermination
      disp('Warning: clean up failed. Please clean up manually');
    end
  end
end

按照此模式运行实际代码会导致错误:

Undefined function or variable "normalTermination".

3 个答案:

答案 0 :(得分:2)

onCleanup对象从do_tuning函数的工作空间外调用函数,因此使用嵌套函数将无济于事...... 事实上,文献说明:

  

Your cleanup routine should never rely on variables that are defined outside of that routine

[编辑 - 基于评论]更好的解决方案是更改问题并在my_clean_up函数中完成所有清理,这可能需要它来确定是否需要做什么(或者具有可以始终应用的通用行为)

如果我们忽视这个警告并解决问题......

使用global变量在工作空间之间传递可变数据是最容易的,因此对于上面的示例代码。 首先将变量定义为全局之前最初将其设置为false(否则变量可能会被覆盖)

function do_tuning
    %# snip
    global normalTermination
    normalTermination = false;
    %# snip

其次在my_clean_up回调函数之前将变量定义为全局使用它来检索值

function my_clean_up
    global normalTermination
    if ~normalTermination
    %# snip

警告与全局变量一样,这很容易受到在错误的时间在别处编辑的全局变量的值的影响。

答案 1 :(得分:0)

以下是对我的示例的修改,使用@RTL建议的全局,按照我的意愿行事。

function do_tuning

  global normalTermination;

  % Set this false to cause a warning messages for control-C or MATLAB coding errors.
  normalTermination = false;
  oc = onCleanup(@() my_clean_up());
  tuningError = tuning_function()   
  if tuningError
    % Set this true to suppress the warning message if a predictable error occurs.
    normalTermination = true;
    error('tuningError')
  end
  % Set this true to suppress the warning message if the function runs to completion.
  normalTermination = true;

  function my_clean_up
    if ~normalTermination
      disp('Warning: clean up failed. Please clean up manually');
    else
      disp('Normal termination, you can relax.');
    end
  end
end

答案 2 :(得分:0)

通过修改onCleanup代码可以实现更优雅的解决方案。您可以轻松添加属性或方法来取消正常行为。示例:

classdef onCleanupCancel < handle

    properties
        active = true;
    end

    properties(SetAccess = 'private', GetAccess = 'public', Transient)
        task = @nop;
    end

    methods
        function h = onCleanupCancel(functionHandle)
            h.task = functionHandle;
        end

        function delete(h)
            if h.active
                h.task();
            end
        end
    end
end
function nop
end

在函数的最后一行,将onCleanupCancel对象的active设置为false ...