我有一个编译的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".
答案 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 ...