I have a textbox that has a fairly hefty _TextChanged
event handler. Under normal typing condition the performance is okay, but it can noticeably lag when the user performs a long continuous action, such as keeping the backspace button pressed to delete a lot of text at once.
For example, the event took 0.2 seconds to complete, but the user is performing one deletion every 0.1 seconds. Thus, it cannot catch up and there will be a backlog of events that needs to be handled, leading to the UI lagging.
However, the event does not need to run for these in-between states, because it only cares about the end result. Is there any way to let the event handler know that it should process only the latest event, and ignore all the previous stale changes?
I've come across this problem several times, and based on my own experience I found this solution simple and neat so far. It is based on Windows Form
but can be converted to WPF
easily.
How it works:
When TypeAssistant
learns that a text change
has happened, it runs a timer. After WaitingMilliSeconds
the timer raises Idle
event. By handling this event, you can do whatever job you wish (such as processing the entered tex). If another text change
occurs in the time frame starting from the time that the timer starts and WaitingMilliSeconds
later, the timer resets.
public class TypeAssistant
{
public event EventHandler Idled = delegate { };
public int WaitingMilliSeconds { get; set; }
System.Threading.Timer waitingTimer;
public TypeAssistant(int waitingMilliSeconds = 600)
{
WaitingMilliSeconds = waitingMilliSeconds;
waitingTimer = new Timer(p =>
{
Idled(this, EventArgs.Empty);
});
}
public void TextChanged()
{
waitingTimer.Change(WaitingMilliSeconds, System.Threading.Timeout.Infinite);
}
}
Usage:
public partial class Form1 : Form
{
TypeAssistant assistant;
public Form1()
{
InitializeComponent();
assistant = new TypeAssistant();
assistant.Idled += assistant_Idled;
}
void assistant_Idled(object sender, EventArgs e)
{
this.Invoke(
new MethodInvoker(() =>
{
// do your job here
}));
}
private void yourFastReactingTextBox_TextChanged(object sender, EventArgs e)
{
assistant.TextChanged();
}
}
Advantages:
WPF
and Windows Form
Disadvantages: