我有一个应用程序,其中包含许多用户控件,每个按钮上都有许多按钮,每个按钮都有一个OnClick事件,该事件执行一些重要操作,然后发送到新的用户控件。
当用户多次单击非常快时,就会出现问题,事件代码在退出到新用户控件之前会执行多次,从而导致问题。
我当前的解决方案是禁用事件处理程序第一行上的按钮,但是对每个窗口和处理程序执行此操作会很麻烦,我该怎么办?
编辑:从 Button 派生并覆盖 OnClick 事件是否是一个很好的解决方案,以便它始终检查"工作"变量,如果它是真的,它不会启动事件?像这样:
public class MyButton : Button
{
private static bool isWorking = false;
protected override void OnClick(EventArgs e)
{
if (!isWorking)
{
isWorking = true;
base.OnClick(e);
isWorking = false;
}
//Else do nothing
}
}
一些timeStamp
来延迟两次点击:
DateTime timeStamp;
//this will handle the clicks with the allowed interval being 0.5 second
//Note that a tick is equal to 1/10,000,000 of second.
private void click_Handler(object sender, EventArgs e) {
if ((DateTime.Now - timeStamp).Ticks < 5000000) return;
timeStamp = DateTime.Now;
//your code goes here ....
}
如果希望所有按钮都等到一个按钮的工作完成,请向窗体添加bool isProcessing
变量。将每个按钮的工作包装在 if (!isProcessing)
中,并在 if 语句的第一行将该标志设置为 true。然后不要忘记在退出 if 之前将其设置回 false。
我假设您正在异步执行所有这些操作,因为如果它们都在同一个线程中,则表单将在处理工作时锁定。不过,这将解决您的问题。
在敏感操作正在进行时禁用控件是我始终应用的典型解决方案。
但是,由于一个屏幕上可能有相当多的控件受到 UI 中的某些单击或更改的影响,因此我通常将窗体设计为具有专用方法,该方法遍历所有受影响的控件并相应地禁用/启用它们。
像这样:
void EnableControls(bool enable)
{
foreach (Control ctl in this.Controls)
ctl.Enabled = enable;
}
同样,您可以将控件分组到相关的存储桶中,以便仅禁用/启用其中一个等。 取决于您的确切需求。
使用计时器还有另一种解决方案 - 禁用按钮,但在 1 秒后启用它。这可以防止紧张的用户多次点击,如果这会对数据造成损害(即每次点击都被视为新操作)。
我会从每个按钮调用相同的函数,然后执行特定的任务:
private void Button_Click(object sender, EventAgrs e)
{
Button btn = sender;
btn.disable = true;
switch (btn.AccessibleName)
// call specific function for the particular button or do it all here
}
我不确定这是否有效,但只是一个想法......
您可以尝试使用面向方面的方法(例如,在Postsharp的帮助下):
- 创建两个方面,一个用于方法输入,一个用于方法退出。在方法条目中,将当前方法标记为"正在处理"(例如,将方法名称添加到哈希集中)。在方法退出中,将该方法标记为"未处理"(将其从哈希集中删除)。然后在方法条目中检查该方法是否正在处理,如果是,则取消该方法(如下所示:https://stackoverflow.com/a/2437794/113858)
- 使用此方面标记所有事件处理程序。