while sirve que para loop funcion c# .net .net-4.0 .net-2.0

c# - sirve - Construcción de.net para bucle while con tiempo de espera



funcion del do en c# (8)

Normalmente empleo un bucle while que continúa intentando alguna operación hasta que la operación sea exitosa o haya transcurrido un tiempo límite

bool success = false int elapsed = 0 while( ( !success ) && ( elapsed < 10000 ) ) { Thread.sleep( 1000 ); elapsed += 1000; success = ... some operation ... }

Sé que hay un par de maneras de implementar esto, pero el punto básico es que repetidamente intento alguna operación con un modo de espera hasta que tenga éxito o haya dormido demasiado tiempo en conjunto.

¿Hay una clase .net / método / etc incorporada para evitar que vuelva a escribir este patrón en todo el lugar? Tal vez la entrada es un Func (de bool) y el tiempo de espera?

Editar
Gracias a todos los que contribuyeron. Opté por el enfoque de dormir () porque era el menos complicado y soy totalmente anti-complejidad =) Aquí está mi (aún necesita ser probada) implícita:

public static bool RetryUntilSuccessOrTimeout( Func<bool> task , TimeSpan timeout , TimeSpan pause ) { if ( pause.TotalMilliseconds < 0 ) { throw new ArgumentException( "pause must be >= 0 milliseconds" ); } var stopwatch = Stopwatch.StartNew(); do { if ( task() ) { return true; } Thread.Sleep( ( int )pause.TotalMilliseconds ); } while ( stopwatch.Elapsed < timeout ); return false; }


La primera solución es utilizar SpinWait.

SpinWait.SpinUntil(() => LoopProcedure(), 1000);

La otra solución es usar Task.Wait ()

var task = Task.Run(() => LoopProcedure()); task.Wait(1000);

Envuelva su bucle en un procedimiento que devuelva valor bool

private bool LoopProcedure() { bool success = false while( ( !success ) { // do some stuff ... } return success; }


Necesitas utilizar Thread.Join . Desde MSDN,

Bloquea el subproceso de llamada hasta que finaliza un subproceso, mientras continúa realizando el bombeo estándar de COM y SendMessage.

Si desea esperar hasta que transcurra un tiempo específico, use el método Thread.Join (TimeSpan) . .NET 3.0, 3.5, 4.0 solamente.

Bloquea el subproceso de llamada hasta que un subproceso termina o transcurre el tiempo especificado , mientras continúa realizando el bombeo estándar de COM y SendMessage.

Este tutorial sobre cómo usar Threads en C # te ayudará.


No sé si hay algo existente, pero creo que podría crear un método para que acepte el tiempo de espera y la función de determinación del éxito. Algo como esto:

public static bool KeepTrying(int timeout, Func<bool> operation) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeout)) { Thread.Sleep(1000); elapsed += 1000; success = operation(); } return success; }

o tal vez su función podría ser más "robusta" y podría combinarla con argumentos flexibles:

public bool KeepTrying(int timeout, Func<object[], bool> operation, params object[] arguments) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeout)) { Thread.Sleep(1000); elapsed += 1000; success = operation(arguments); } return success; }


Otros han mencionado técnicas de sincronización de subprocesos, que le permitirían esperar hasta que alguna tarea finalice. Sin embargo, si desea continuar el sondeo cada segundo como lo está haciendo, puede ajustar ese método de la siguiente manera:

void Main() { Timeout(() => {return false;}); } public void Timeout(Func<bool> action, int timeout) { bool success = false; int elapsed = 0; while( ( !success ) && ( elapsed < timeout ) ) { Thread.Sleep( 1000 ); elapsed += 1000; success = action(); } Console.WriteLine("timed out."); }


Podrías envolver tu algoritmo en un método:

public bool RetryUntilSuccessOrTimeout(Func<bool> task, TimeSpan timeSpan) { bool success = false; int elapsed = 0; while ((!success) && (elapsed < timeSpan.TotalMilliseconds)) { Thread.Sleep(1000); elapsed += 1000; success = task(); } return success; }

y entonces:

if (RetryUntilSuccessOrTimeout(() => SomeTask(arg1, arg2), TimeSpan.FromSeconds(10))) { // the task succeeded }



Puede abstraer un poco su código y generalizar el Tiempo de espera:

int timer = 0; while (!SomeOperation(...) && Timeout(ref timer, 1000, 10000)); public bool Timeout(ref int timer, int increment, int maximum) { timer += increment; Thread.Sleep(increment); return timer < maximum; }


Realmente no debería tener que usar Sleep() para esperar a que se completen las tareas. Usted desperdicia un promedio de 500 ms después de que la tarea se haya completado al hacer esto.

Debería poder hacer esto de manera determinista utilizando la biblioteca paralela de tareas, vea here por ejemplo.

Este ejemplo muestra cómo usar el método Wait, o su equivalente en la clase Task, para esperar en una sola tarea. También muestra cómo usar los métodos estáticos WaitAll y WaitAny para esperar en múltiples tareas.