2010-12-02 45 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(); 
    } 
}