默认情况下,按 Alt + 。或在评估中调用Abort[]
会导致当前评估输入中止。但是当在FrontEnd中工作时,我们通常会向内核发送一系列输入。例如,如果我们在一个Cell
中的不同行上键入以下三个表达式,然后按 Shift + Enter ,我们将获得无限评估:
f := CheckAbort[Pause[.1], Abort[]]
While[True, f]
While[True, f]
While[True, f]
要停止此无限评估,我们必须按 Alt + 。三次。
如何在上面的示例中定义函数f
,以便按 Alt + 。 一次将在不退出内核的情况下中止对输入的完整序列的评估?
修改
我认为如果FrontEnd为MathKernel创建输入队列,它可能也会取消此队列。
答案 0 :(得分:6)
Sasha建议只使用四个单元格是有效的,因为这基本上就是FrontEnd所做的事情,向内核提交了几个不同的评估。如果您坚持使用一个单元格,请将其包裹在parens(CompoundExpression
)中,这会导致这四行被视为一个评估(请注意;
也需要):
(
f := CheckAbort[Pause[.1], Abort[]];
While[True, f];
While[True, f];
While[True, f]
)
然后,发布的一次中止将作为一个整体中止评估。
答案 1 :(得分:1)
我找到了一种方法来做我想做的事。唯一的问题是,此刻我不知道如何检查FrontEnd是否有一些未决输入。我被迫等待1秒钟。在大多数情况下,它足以将所有未决输入发送到内核,但可能并非总是如此。
In[1]:= $new$PreRead = False;
AbortAllPendingInputs :=
AbortProtect[If[! $new$PreRead, $new$PreRead = True;
$TimeOfAbort = SessionTime[];
last$PreRead = ToString[Definition[$PreRead], InputForm];
ClearAll[$PreRead];
$PreRead := If[TrueQ[SessionTime[] - $TimeOfAbort < 1], "",
$new$PreRead = False;
ClearAll[$PreRead];
If[last$PreRead === "Null", #,
ToExpression[last$PreRead]; $PreRead@#]
] &;]];
In[3]:= f := CheckAbort[Pause[10], AbortAllPendingInputs; Abort[]]
In[4]:= While[True, f]
While[True, f]
While[True, f]
Out[4]= $Aborted
但我仍在寻找更优雅的解决方案。我认为如果FrontEnd为MathKernel创建一个输入队列,它可能也会取消这个队列。
答案 2 :(得分:1)
Alexey,请尝试使用此版本的代码并告诉我是否/何时失败:
AbortAllPendingInputs :=
AbortProtect[
$new$PreRead = True;
$TimeOfAbort = SessionTime[];
last$PreRead = $PreRead;
$PreRead =
If[
TrueQ[SessionTime[] - $TimeOfAbort < 1],
"",
$new$PreRead = False; $PreRead = last$PreRead; $PreRead[#]
] &;
] /; ! TrueQ[$new$PreRead]