La ""teoria"" dice:
1) prepari il "processo" separato da mandare in esecuzione
2) intercetti gli "StandardOutput" e "StandardError" del processo, mediante PIPE
3) mandi in esecuzione il PROCESSO
4.1) cicli in attesa che il PROCESSO termini e nel frattempo leggi out/err intercettati
OPPURE
4.2) net thread principale dell'applicazione ATTENDI che il PROCESSO termini
4.3) in thread separato, leggi out/err intercettati
Il problema e' questo:
a) NON puoi far affidamento sul fatto che gli out/err intercettati siano chiusi o no PERCHE' non sai se il processo sia partito o no
b) NON SEI TU che fai partire il processo ANCHE se, da codice, gli hai detto di partire.
Quello che sai PER CERTO e' che e' responsabilita' della classe usata per gestire il PROCESSO dirti SE il processo e' partito, in esecuzione o terminato.
Lo sa lei, perche' interagisce direttamente con il SO.
Da tutto questo si evince che
process.Start();
while (!process.StandardOutput.EndOfStream)
...
NON PUO' funzionare.
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.waitforexit?view=net-5.0
OVVIAMENTE fare la Join su un thread locale, NON CENTRA un'acciderbolina con la gestione di un' ALTRO processo (che ha i SUOI thread).
ANCHE per i thread locali, chiamare la "Start()" NON FA PARTIRE AUTOMATICAMENTE il thread. Semplicemente lo mette nella lista di quelli da far partire. PRIMA O POI partira'. E" la classe Thread che si occupa di gestirlo.
SE tu chiami la Join() su un thread NON partito, la Join FUNZIONA!
Perche' la classe Thread SA che tu ti stai mettendo in attesa del TERMINE del thread ma questo non solo non e ancora terminato, ma non e' nemmeno andato in esecuzione!
Stessa cosa per i processi.