2010-12-02 19 views
7

¿Existe una solución/idea/estrategia simple para crear una función equivalente setTimeout en una aplicación WinForms. Principalmente soy un desarrollador web, pero no estoy seguro de cómo hacerlo en una aplicación de WinForms. Básicamente, tengo un cuadro de texto, y después de cada pulsación quiero ejecutar una tarea para rellenar una lista (como una cosa de autocompletar tipo) pero quiero poder cancelar (por ejemplo, clearTimeout) si el usuario sigue ingresando caracteres ...Formas de pago equivalentes a javascript setTimeout

Mi única conjetura es tal vez utilizar un BackGroundWorker y hacerlo dormir inicialmente, y mientras está durmiendo, podría cancelarse, si el usuario deja de ingresar las claves y el período de suspensión finaliza, luego ejecuta la tarea, etc.

(no me importa si es un ejemplo de C# o Vb.Net)

+0

[SetTimeout de Javascript, y SetInterval clearInterval equivalente en C#] (https://stackoverflow.com/questions/40502596/javascripts-settimeout-setinterval-and-clearinterval-equivalent-in-c-sharp/40609390# 40609390) – Koray

Respuesta

11

puede utilizar un System.Timers.Timer: set AutoReset en false y el uso de métodos de arranque/parada y crear un controlador para el evento transcurrido.

11
public void setTimeout(Action TheAction, int Timeout) 
    { 
     Thread t = new Thread(
      () => 
      { 
       Thread.Sleep(Timeout); 
       TheAction.Invoke(); 
      } 
     ); 
     t.Start(); 
    } 
+0

gracias por publicar una buena solución – davidsleeps

+2

No recomendaría usar este método. ¿Crear un hilo completo solo para una sola operación? Overkill. Use la clase Timer provista en el otro método para algo más productivo. Según esta respuesta, se asigna 1 MB de memoria para cada nuevo hilo. http://stackoverflow.com/a/2744464/881111 - Recuerde, el OP dijo que iba a ejecutar esto después de cada pulsación de tecla ... así que considere 1 MB de memoria Y un nuevo hilo para cada pulsación de tecla. Mala idea. – Nuzzolilo

+0

No solo es una mala idea. Esto probablemente tiene problemas de concurrencia –

0
public void setTimeout(Action act, int timeout) 
    { 
     Action action =() => 
     { 
      Thread.Sleep(Timeout); 
      act(); 
     }; 

     new Thread(() => Invoke(action)).Start(); 
    } 
+0

¿Esto funciona? – theonlygusti

0

me gustaría recomendar el uso de programación reactiva para esto. Consulte https://github.com/Reactive-Extensions/Rx.NET para las extensiones reactivas para .NET y http://reactivex.io/ para obtener información general sobre la programación reactiva.

Me temo que sólo están familiarizados con la biblioteca JavaScript reactiva, por lo que no se puede dar un ejemplo C-Sharp, pero en JavaScript que trabajaría algo como esto:

Rx.Observable.fromEvent(..eventdetails..) 
    .debounceTime(300) 
    .distinctUntilChanged() 
    .subscribe(eventHandler); 

Con una configuración como esta, puede encadenar a los operadores para mapear y combinar todo tipo de eventos desde una fuente hasta un suscriptor. El ejemplo simple anterior reacciona a un evento, un keyUp por ejemplo, y espera hasta que no haya keyUp nuevo durante 300 ms y luego llama al eventHandler, pero solo si el nuevo valor (después de 300ms) es diferente del último valor emitido.

0

Esta es mi manera, use la función de sintaxis C# 7.0. Algunos difieren con js, cuando se ejecuta la acción de tiempo de espera, entonces no será claro.

internal static class JsStyleTimeout 
{ 
    private static readonly ConcurrentDictionary<int, Thread> InnerDic; 

    private static int _handle; 

    static JsStyleTimeout() 
    { 
     InnerDic = new ConcurrentDictionary<int, Thread>(); 
    } 

    public static int Set(Action action, int delayMs) 
    { 
     var handle = Interlocked.Increment(ref _handle); 

     var thread = new Thread(new ThreadStart(delegate 
     { 
      Thread.Sleep(delayMs); 
      InnerDic.TryRemove(handle, out var _); 
      Task.Factory.StartNew(action); 
     })); 
     InnerDic.TryAdd(handle, thread); 

     thread.Start(); 
     return handle; 
    } 

    public static void Clear(int handle) 
    { 
     if (InnerDic.TryRemove(handle, out var thread)) 
      thread.Abort(); 
    } 
} 
Cuestiones relacionadas