How to abort evaluation of a sequence of inputs?

自闭症网瘾萝莉.ら 提交于 2020-01-09 10:55:48

问题


By default pressing Alt+. or calling Abort[] within the evaluation causes abort of the currently evaluating input. But when working in the FrontEnd we usually send to the kernel a sequence of inputs. For example, if we type the following three expressions on separate lines in one Cell and then press Shift+Enter we get infinite evaluation:

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

To stop this infinite evaluation we must to press Alt+. three times.

How to define the function f in the example above in such a way that pressing Alt+. one time will abort the evaluation of the full sequence of inputs without quitting the kernel?

EDIT

I think that if the FrontEnd creates an input queue for MathKernel it probably can also cancel this queue.


回答1:


Sasha's suggestion to just use four cells is valid, because that's basically what the FrontEnd does anyway, submitting several distinct evaluations to the Kernel. If you insist in using one cell, wrap it in parens (CompoundExpression), which causes those four lines to be treated as one evaluation (note the need for ; too):

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

Then, one abort issued will abort the evaluation as a whole.




回答2:


I have found a way to do what I want. The only problem is that at this moment I do not know how to check whether the FrontEnd has some pending inputs. I am forced just to wait 1 second. In the most cases it is sufficient time for sending all pending inputs to the kernel but probably not always.

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

But I am still looking for more elegant solution. I think that if the FrontEnd creates an input queue for MathKernel it probably can also cancel this queue.




回答3:


Alexey, please try this version of your code and tell me if/when it fails:

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]


来源:https://stackoverflow.com/questions/5625648/how-to-abort-evaluation-of-a-sequence-of-inputs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!