2010-12-02 82 views
7

是否有一个简单的解决方案/想法/策略在WinForms应用程序中创建setTimeout等效函数。我主要是一个Web开发人员,但我不知道如何在WinForms应用程序中执行此操作。基本上,我有一个文本框,并在每次击键后,我想运行一个任务来填充列表(如自动完成类型thingy),但希望能够取消(如clearTimeout),如果用户不断输入字符...Winforms等效的javascript setTimeout

我唯一的猜测是可能使用BackGroundWorker,并使它最初睡眠,并在睡眠时,它可能会被取消,如果用户停止输入密钥并且睡眠期结束,则它会去执行任务等

(我不关心,如果一个例子是C#或Vb.Net)

+0

[JavaScript的setTimeout的,和setInterval的等效ClearInterval在c#](https://stackoverflow.com/questions/40502596/javascripts-settimeout-setinterval-and-clearinterval-equivalent-in-c-sharp/40609390# 40609390) – Koray 2017-08-03 12:40:07

回答

11

您可以使用System.Timers.Timer:设置自动复位为false,并使用启动/停止的方法和创建针对逝去事件的处理程序。

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

感谢发布一个整洁的解决方案 – davidsleeps 2012-10-09 21:45:08

+2

我不会推荐使用这种方法。为一个操作创建一个完整的线程?矫枉过正。使用另一种方法中提供的Timer类来获得更具生产价值的东西。根据这个答案,为每个新线程分配1 MB内存。 http://stackoverflow.com/a/2744464/881111 - 请记住,OP表示他将在每次按键之后运行此操作...因此,请考虑1 MB内存和每个按键的新线程。馊主意。 – Nuzzolilo 2014-05-29 05:09:05

+0

不仅是一个坏主意。这可能有并发问题 – 2017-02-05 23:18:44

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

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

我推荐使用反应式编程这一点。请参阅https://github.com/Reactive-Extensions/Rx.NET以了解Reactive Extensions for .NET和http://reactivex.io/以获取有关反应式编程的一般信息。

我怕我只熟悉JavaScript的反应式库,所以我不能给你一个C-夏普的例子,但在JavaScript它会工作是这样的:

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

使用这样的设置,您可以链接运营商来映射和合并从源到订阅者的各种事件。上面这个简单的例子反应了一个事件,例如keyUp,并且等待300毫秒没有新的keyUp,然后调用eventHandler,但是只有当新值(在300ms之后)与最后发出的值不同时。

0

这是我的方式,使用C#7.0语法功能。 有些与js不同,当执行超时动作时将不能清除。

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(); 
    } 
}