是否有一个简单的解决方案/想法/策略来在WinForms应用程序中创建setTimeout等效函数。我主要是一个Web开发人员,但我不确定如何在WinForms应用程序中进行此操作。基本上,我有一个文本框,每次击键后我想运行一个任务来填充一个列表(比如一个自动完成类型的东西),但是如果用户继续输入字符,希望能够取消(例如clearTimeout)...
我唯一的猜测是可能使用BackGroundWorker并使其初始睡眠,当它处于休眠状态时,它可以被取消,如果用户停止输入密钥并且睡眠期结束,则它会继续运行任务等< / p>
(我不在乎一个例子是C#还是Vb.Net)
答案 0 :(得分:28)
我知道这是一个老问题,但另一种解决方案是使用Task.Delay(delay).ContinueWith((task) => { /* Code */ });
。
或有await Task.Delay(delay);
答案 1 :(得分:12)
您可以使用System.Timers.Timer:将AutoReset设置为false并使用Start / Stop方法并为Elapsed事件创建处理程序。
答案 2 :(得分:11)
public void setTimeout(Action TheAction, int Timeout)
{
Thread t = new Thread(
() =>
{
Thread.Sleep(Timeout);
TheAction.Invoke();
}
);
t.Start();
}
答案 3 :(得分:3)
计时器实现:
public void SetTimeout(Action action, int timeout)
{
var timer = new System.Windows.Forms.Timer();
timer.Interval = timeout;
timer.Tick += delegate (object sender, EventArgs args)
{
action();
timer.Stop();
};
timer.Start();
}
答案 4 :(得分:2)
我可以提出以下建议
internal class Timeout : System.Timers.Timer
{
public Timeout (Action action, double delay)
{
this.AutoReset = false;
this.Interval = delay;
this.Elapsed += (sender, args) => action();
this.Start();
}
}
// Example
var timeout = new Timeout(() => {
Console.WriteLine("init 1");
}, 500);
timeout.Stop();
答案 5 :(得分:0)
public void setTimeout(Action act, int timeout)
{
Action action = () =>
{
Thread.Sleep(Timeout);
act();
};
new Thread(() => Invoke(action)).Start();
}
答案 6 :(得分:0)
我建议使用反应式编程。有关Reactive Extensions for .NET的信息,请参阅https://github.com/Reactive-Extensions/Rx.NET;有关Reactive编程的一般信息,请参阅http://reactivex.io/。
我担心我只熟悉JavaScript反应库,所以我不能给你一个C-Sharp的例子,但在JavaScript中它的工作方式是这样的:
Rx.Observable.fromEvent(..eventdetails..)
.debounceTime(300)
.distinctUntilChanged()
.subscribe(eventHandler);
使用这样的设置,您可以链接运营商以映射和合并从源到订户的各种事件。上面的简单示例对一个事件(例如一个keyUp)做出反应,并等待300毫秒没有新的keyUp,然后调用eventHandler,但前提是新值(在300ms之后)与最后一个发射值不同。 / p>
答案 7 :(得分: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();
}
}
答案 8 :(得分:0)
您还可以使用:
Delay.Do(3000 /*in ms*/, () => { /* Do somthing */ });
Delay.Do
在哪里:
using System;
using System.Timers;
public class Delay
{
public static void Do(int after, Action action)
{
if (after <= 0 || action == null) return;
var timer = new Timer { Interval = after, Enabled = false };
timer.Elapsed += (sender, e) =>
{
timer.Stop();
action.Invoke();
timer.Dispose();
GC.SuppressFinalize(timer);
};
timer.Start();
}
}
注意:在UI线程中更新控件时,请使用Control.Invoke
:
Delay.Do(2000, () => { lblOk.Invoke((MethodInvoker)(() => { lblOk.Visible = false; })); });