4

默认情况下,在评估中按Alt+.或调用Abort[]会导致当前评估输入的中止。但是在前端工作时,我们通常会向内核发送一系列输入。例如,如果我们在单独的一行中键入以下三个表达式Cell,然后按Shift+ Enter,我们将得到无限求值:

f := CheckAbort[Pause[.1], Abort[]]
While[True, f]
While[True, f]
While[True, f]

要停止这种无限求值,我们必须按Alt+.三次。

如何f在上面的示例中定义函数,即按下Alt+. 一次将中止对完整输入序列的评估而不退出内核

编辑

我认为如果 FrontEnd 为 MathKernel 创建一个输入队列,它可能也可以取消这个队列。

4

3 回答 3

6

Sasha 只使用四个单元的建议是有效的,因为这基本上是前端所做的,向内核提交几个不同的评估。如果您坚持使用一个单元格,请将其包裹在括号 ( CompoundExpression) 中,这会导致这四行被视为一个评估(请注意;也需要):

(
   f := CheckAbort[Pause[.1], Abort[]];
   While[True, f];
   While[True, f];
   While[True, f]
)

然后,发出的一个中止将中止整个评估。

于 2011-04-11T19:11:52.003 回答
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]
于 2011-04-13T07:30:00.640 回答
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 创建一个输入队列,它可能也可以取消这个队列。

于 2011-04-11T20:01:27.630 回答