How to catch interrupts generated by TimeConstrained?
Mathematica has the CheckAbort
function which allows to catch and handle user-generated and programmatic Abort
s. But it does not allow to catch interrupts generated by such functions as TimeConstrained
and MemoryConstrained
:
TimeConstrained[CheckAbort[Pause[100], Print["From CheckAbort"]], 1]
(does not print "From CheckAbort"
).
Is there a way to catch such interrupts in Mathe开发者_如何学Cmatica?
EDIT: I do know that third argument of TimeConstrained
and MemoryConstrained
allows to evaluate some code in the case of interrupt but this way is not what I need: I need a way to handle such interrupts entirely inside of my function allowing a user do not care of its internals.
P.S. The reason why I need this is that I have a function that creates MathLink
objects which must be closed in the case of any interrupts or aborts but not in other cases.
The construct for this is available in undocumented form.
Internal`WithLocalSettings[
preprocessing,
code,
postprocessing]
will cause postprocessing to take place before returning from aborts or various types of jumps.
See also:
Reliable clean-up in Mathematica
Import big files/arrays with mathematica
Daniel Lichtblau
Here is improved version of WReach's solution (he suggested it in a comment to the answer by Daniel Lichtblau). I should redefine my function f
as follows (and now call it as ff
):
ClearAll[ff];
SetAttributes[ff, HoldAllComplete];
ff[expr_] /; (Unset[done]; True) :=
Internal`WithLocalSettings[Null, done = f[expr],
AbortProtect[If[! ValueQ[done], Print["Interrupt!"]]; Unset[done]]]
Examples:
ff[1 + 1]
(*=>f[2]*)
TimeConstrained[ff[Pause[10]; 1 + 1], 1]
(*=> prints "Interrupt!"*)
TimeConstrained[ff[Pause[.10]; 1 + 1], 1]
(*=>f[2]*)
TimeConstrained[Pause[100], 1, Print["-->Aborted"]]
and
MemoryConstrained[100!, 1, Print["-->Aborted"]]
I am putting this here just to flesh out Danny's answer. I think this is clearly a bug in CheckAbort
, and would use this as a workaround:
Attributes[myCheckAbort] = {HoldAll};
myCheckAbort[arg1_, arg2_] := Block[
{res, aborted},
WithCleanup[
aborted = True
,
res = arg1;
aborted = False;
res
,
If[aborted,
arg2;
res = $Aborted
]
]
]
精彩评论