valid - method summary c#
C#- Haciendo un proceso. Comience a esperar hasta que el proceso se inicie (9)
Necesito asegurarme de que se esté ejecutando un proceso antes de continuar con un método.
La declaración es:
Process.Start("popup.exe");
¿Puede hacer un comando WAIT o establecer un retraso en este valor?
¿Está seguro de que el método de Start
vuelve antes de que comience el proceso secundario? Siempre tuve la impresión de que Start
inicia el proceso hijo de forma sincrónica.
Si desea esperar hasta que su proceso hijo finalice algún tipo de inicialización, entonces necesita comunicación entre procesos. Consulte Comunicación entre procesos para Windows en C # (.NET 2.0) .
¿Quieres decir esperar hasta que esté hecho? Luego use Process.WaitForExit
:
var process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "popup.exe"
}
};
process.Start();
process.WaitForExit();
Alternativamente, si se trata de una aplicación con una interfaz de usuario que está esperando ingresar en un bucle de mensajes, puede decir:
process.Start();
process.WaitForInputIdle();
Por último, si ninguno de estos se aplica, solo Thread.Sleep
durante un tiempo razonable:
process.Start();
Thread.Sleep(1000); // sleep for one second
Aquí una implementación que utiliza un System.Threading.Timer
. Tal vez un poco demasiado para su propósito.
private static bool StartProcess(string filePath, string processName)
{
if (!File.Exists(filePath))
throw new InvalidOperationException($"Unknown filepath: {(string.IsNullOrEmpty(filePath) ? "EMPTY PATH" : filePath)}");
var isRunning = false;
using (var resetEvent = new ManualResetEvent(false))
{
void Callback(object state)
{
if (!IsProcessActive(processName)) return;
isRunning = true;
// ReSharper disable once AccessToDisposedClosure
resetEvent.Set();
}
using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
{
Process.Start(filePath);
WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
}
}
return isRunning;
}
private static bool StopProcess(string processName)
{
if (!IsProcessActive(processName)) return true;
var isRunning = true;
using (var resetEvent = new ManualResetEvent(false))
{
void Callback(object state)
{
if (IsProcessActive(processName)) return;
isRunning = false;
// ReSharper disable once AccessToDisposedClosure
resetEvent.Set();
}
using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
{
foreach (var process in Process.GetProcessesByName(processName))
process.Kill();
WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
}
}
return isRunning;
}
private static bool IsProcessActive(string processName)
{
return Process.GetProcessesByName(processName).Any();
}
Como otros ya han dicho, no es inmediatamente obvio lo que estás preguntando. Asumiré que desea iniciar un proceso y luego realizar otra acción cuando el proceso "esté listo".
Por supuesto, el "está listo" es un poco difícil. Dependiendo de cuáles sean sus necesidades, puede encontrar que simplemente esperar es suficiente. Sin embargo, si necesita una solución más sólida, puede considerar el uso de un Mutex denominado para controlar el flujo de control entre sus dos procesos.
Por ejemplo, en su proceso principal, puede crear una exclusión mutua con nombre e iniciar un hilo o tarea que esperará. A continuación, puede iniciar el segundo proceso. Cuando ese proceso decide que "está listo", puede abrir la exclusión mutua nombrada (tiene que usar el mismo nombre, por supuesto) y señalar el primer proceso.
En primer lugar: sé que esto es bastante antiguo, pero todavía no hay una respuesta aceptada, así que quizás mi enfoque ayude a alguien más. :)
Lo que hice para resolver esto es:
process.Start();
while (true)
{
try
{
var time = process.StartTime;
break;
}
catch (Exception) {}
}
La asociación var time = process.StartTime
lanzará una excepción siempre y cuando el proceso no se inicie. Entonces, una vez que pasa, es seguro asumir que el proceso se está ejecutando y seguir trabajando con él. Estoy usando esto para esperar a que se inicie el proceso java, ya que toma algo de tiempo. De esta manera, debe ser independiente de qué máquina está ejecutando la aplicación en lugar de usar Thread.Sleep()
.
Entiendo que esta no es una solución muy limpia, pero puedo pensar en la única que debería ser independiente del rendimiento.
Estoy de acuerdo con Tom. Además, para verificar los procesos mientras se ejecuta Thread.Sleep, verifique los procesos en ejecución. Algo como:
bool found = 0;
while (!found)
{
foreach (Process clsProcess in Process.GetProcesses())
if (clsProcess.Name == Name)
found = true;
Thread.CurrentThread.Sleep(1000);
}
La respuesta de ''ChrisG'' es correcta, pero necesitamos actualizar MainWindowTitle cada vez y es mejor verificar si está vacío ... así:
var proc = Process.Start("popup.exe");
while (string.IsNullOrEmpty(proc.MainWindowTitle))
{
System.Threading.Thread.Sleep(100);
proc.Refresh();
}
Para ampliar un poco la idea de @ ChrisG, considere usar process.MainWindowHandle y ver si el bucle de mensajes de la ventana está respondiendo. Utilice p / invocar esta API Win32: SendMessageTimeout . Desde ese enlace:
Si la función tiene éxito, el valor devuelto es distinto de cero. SendMessageTimeout no proporciona información sobre el tiempo de espera de ventanas individuales si se utiliza HWND_BROADCAST.
Si la función falla o se agota, el valor de retorno es 0. Para obtener información de error extendida, llame a GetLastError. Si GetLastError devuelve ERROR_TIMEOUT, la función agotó el tiempo de espera.
También necesité esto una vez, e hice una comprobación del título de la ventana del proceso. Si es la que usted espera, puede estar seguro de que la aplicación se está ejecutando. La aplicación que estaba revisando necesitaba algo de tiempo para el inicio y este método funcionó bien para mí.
var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
Thread.Sleep(10);
}