# How to ask FrontEnd to wait until an Evaluation has finished?

I am writing a notebook programmatically. I would like the FrontEnd to wait until an evaluation is finished, before continuing. This is best explained with examples:

The following opens a notebook, writes a text cell, writes an input cell, evaluates it, and continues to write more text cells. Notice that the evaluation doesn't finish until the the the the FrontEnd finishes.

NotebookWrite[exampleNB,
Cell["example of evaluating input programmatically",
"Text"]]; NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 1]];
SelectionMove[exampleNB, Previous, Cell];
SelectionEvaluate[exampleNB];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];
Pause[5];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];


This is related to a similar post, the answer to which almost gets me to a solution. How to wait a Cell in a Notebook to be executed until another Notebook's Cell expressions executed?

That post's solution doesn't work for my case, because this will evaluate all input cells:

NotebookWrite[exampleNB,
Cell["example of evaluating input programattically",
"Text"]]; NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 1]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB, InsertResults -> True];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];
Pause[1];
NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 1]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB, InsertResults -> True];
Pause[1];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];


I've tried a solution with CellTags. This works, but there is a problem: there is no output from the evaluation.

NotebookWrite[exampleNB,
Cell["example of evaluating input programattically",
"Text"]]; NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 1]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB,
EvaluationElements -> {"CellTags" -> 1}];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];
Pause[2];
NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 2]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB, EvaluationElements -> {"CellTags" -> 2}];
Pause[2];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];


One might think that adding the InsertResults->True option would insert results, but it doesn't:

NotebookWrite[exampleNB,
Cell["example of evaluating input programattically",
"Text"]]; NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 1]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB, InsertResults -> True,
EvaluationElements -> {"CellTags" -> 1}];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];
Pause[2];
NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]" , "Input", CellTags -> 2]];
SelectionMove[exampleNB, Previous, Cell];
NotebookEvaluate[exampleNB, InsertResults -> True,
EvaluationElements -> {"CellTags" -> 2}];
Pause[2];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]];


I think that this may be a buglet.

Is there a work-around? My goal here is simple. Get the input's evaluation to display before the rest of the cells are written.

It may seem like a strange thing to want to do, but if is anyone is interested a out why, I'll add this as a comment.

• Maybe TaskWait may help Mar 21 at 17:16
• I think your best option is to write the cells you want to evaluate into a separate notebook, evaluate that, and copy the results where you need them. (At least that's what I've ended up doing when I had this issue) Mar 21 at 18:14
• I looked at TaskWait. That is a rabbit hole that I will spelunk if need be. Holding out hope for a simpler trick. Mar 21 at 18:20
• @Lukas that’s a viable solution. I’ll try it and see. If successful, I’ll report back. Mar 21 at 18:22
• @LukasLang, That strategy works for me. Mar 21 at 21:21

You could try the following approach, with a secondary kernel (K2) and using CellInformation to check if a cell or notebook is currently in the "Evaluating" state:

1. Get the current evaluator names:
evaluators = EvaluatorNames /. Options[$FrontEnd, EvaluatorNames];  1. Add a "K2" kernel if there isn't one: SetOptions[$FrontEnd, Union[Join[evaluators, {"K2" -> {"AutoStartOnLaunch" -> False}}]]]

1. Function which checks if any cell in a notebook is currently evaluating:
NotebookEvaluatingQ[nb_] := Module[{},
SelectionMove[nb, All, Notebook];
Or @@ Map["Evaluating" /. # &, DeveloperCellInformation[nb]]
]

1. Make a new notebook with a "K2" kernel:
nb = CreateDocument[{}, Evaluator -> "K2"]

1. Write a test input Pause[2], evaluate it and pause until it is done. Repeat for a total of three times:
SelectionMove[nb, All, Notebook];
FrontEndTokenExecute[nb, "Cut"];
Do[
NotebookWrite[nb,
Cell[BoxData[MakeBoxes[Pause[2], StandardForm]], "Input"]];
SelectionMove[nb, Previous, Cell];
FrontEndTokenExecute[nb, "Evaluate"];
SelectionMove[nb, Previous, Cell];
While[NotebookEvaluatingQ[nb], Pause[.1]];
SelectionMove[nb, After, Notebook];
, 3]

• This works very well for my purposes and is the best answer to the original question---thank you. I am also accepting this as an answer. Mar 27 at 15:00

An example of evaluating the expression outside the notebook and then write the result in the notebook.

exampleNB = CreateDocument[];
NotebookWrite[exampleNB,
Cell["example of evaluating input programmatically",
"Text"]]; NotebookWrite[exampleNB,
Cell["D[Sin[ RandomReal[] x],x]", "Input", CellTags -> 1]];
NotebookWrite[exampleNB,
Cell[StandardForm@ToString@D[Sin[ RandomReal[] x], x], "Output"]];
Pause[2];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]]
Pause[2];
NotebookWrite[exampleNB, Cell[RandomWord[], "Text"]]
`
• Clever solution!; accepted it as answered. Also recognizing Lukas Lang for his suggestion. Mar 23 at 12:15