我需要能够延迟某些控件(如按钮)的事件处理程序,例如在实际事件发生1秒后(例如单击事件)..这可能是.net框架吗?
我使用计时器并从计时器的tick事件中调用我的代码,如下所示,但我不确定这是否是最好的方法!
void onButtonClick( ..)
{
timer1.Enabled = true;
}
void onTimerTick( ..)
{
timer.Enabled = false;
CallMyCodeNow();
}
答案 0 :(得分:15)
也许你可以创建一个创建计时器的方法?
void onButtonClick(object sender, EventArgs e)
{
Delay(1000, (o,a) => MessageBox.Show("Test"));
}
static void Delay(int ms, EventHandler action)
{
var tmp = new Timer {Interval = ms};
tmp.Tick += new EventHandler((o, e) => tmp.Enabled = false);
tmp.Tick += action;
tmp.Enabled = true;
}
答案 1 :(得分:5)
在回答你的问题之前,只要阅读了主要问题页面中的摘要位,计时器正是我要建议的。
这看起来很干净。这意味着,如果需要,您可以通过再次禁用计时器轻松“取消”延迟事件。它还可以在UI线程中完成所有操作(但不需要重入),这使得生活比其他替代方案更简单。
答案 2 :(得分:5)
如果您只为一个控件执行此操作,则计时器方法可以正常工作。支持多种控件和事件类型的更强大的方法如下所示:
class Event
{
public DateTime StartTime { get; set; }
public Action Method { get; set; }
public Event(Action method)
{
Method = method;
StartTime = DateTime.Now + TimeSpan.FromSeconds(1);
}
}
在表单中维护Queue<Event>
,并将需要延迟的UI事件添加到队列中,例如:
void onButtonClick( ..)
{
EventQueue.Enqueue(new Event(MethodToCall));
}
让你的计时器每秒钟滴答10次左右,并使其Tick事件处理程序如下所示:
void onTimerTick()
{
if (EventQueue.Any() && EventQueue.First().StartTime >= DateTime.Now)
{
Event e = EventQueue.Dequeue();
e.Method;
}
}
答案 3 :(得分:4)
我的解决方案使用System.Threading.Timer:
public static class ExecuteWithDelay
{
class TimerState
{
public Timer Timer;
}
public static Timer Do(Action action, int dueTime)
{
var state = new TimerState();
state.Timer = new Timer(o =>
{
action();
lock (o) // The locking should prevent the timer callback from trying to free the timer prior to the Timer field having been set.
{
((TimerState)o).Timer.Dispose();
}
}, state, dueTime, -1);
return state.Timer;
}
}
答案 4 :(得分:3)
对于那些仅限于.NET 2.0的人来说,这是对Bengt有用的解决方案的另一种看法:
/// <summary>
/// Executes the specified method in a delayed context by utilizing
/// a temporary timer.
/// </summary>
/// <param name="millisecondsToDelay">The milliseconds to delay.</param>
/// <param name="methodToExecute">The method to execute.</param>
public static void DelayedExecute(int millisecondsToDelay, MethodInvoker methodToExecute)
{
Timer timer = new Timer();
timer.Interval = millisecondsToDelay;
timer.Tick += delegate
{
// This will be executed on a single (UI) thread, so lock is not necessary
// but multiple ticks may have been queued, so check for enabled.
if (timer.Enabled)
{
timer.Stop();
methodToExecute.Invoke();
timer.Dispose();
}
};
timer.Start();
}
答案 5 :(得分:1)
使用Reactive Extensions:
首先,安装nuget包
PM> Install-Package Rx-Main
代码:
private void CallMyCodeNow()
{
label1.Text = "reactivated!";
}
private void Form1_Load(object sender, EventArgs e)
{
var o = Observable.FromEventPattern<EventHandler, EventArgs>(
handler => button1.Click += handler
, handler => button1.Click -= handler
)
.Delay(TimeSpan.FromSeconds(5))
.ObserveOn(SynchronizationContext.Current) // ensure event fires on UI thread
.Subscribe(
ev => CallMyCodeNow()
, ex => MessageBox.Show(ex.Message)
);
}
答案 6 :(得分:0)
如果您正在寻找更实用的解决方案,您可能需要查看我的Reactive LINQ project。该链接没有显示如何解决您遇到的特定问题,但应该可以使用其中描述的技术(在整个4篇文章系列中)以相当优雅的方式解决。
答案 7 :(得分:-3)
您可以使用:
Thread.Sleep(1000);
这将暂停当前线程一秒钟。所以我会这样做......
最诚挚的问候!