I have a function that is being called when the user is typing in a search box. I want to wait for the user to finish typing before I actually execute the function. I know how to easily accomplish this in JavaScript with timeouts, but how would I go about doing the same thing in C#? Also, how long should I wait before I assume the user is done typing? 100ms?
6 Answers
If you're comfortable using the Reactive (Rx) framework, then you could implement this functionality using its built in throttling extremely quickly.
Here is an article on the subject: Rx Can Improve UI Responsiveness
And some code stolen & modified from the article:
var textObserver = (from text in Observable.FromEvent<TextChangedEventArgs>(_app.myTextField, "TextChanged")
select text).Throttle(TimeSpan.FromSeconds(.5));
_searchObserver = textObserver.Subscribe(textChangedEvent =>
{
var tb = (TextBox)textChangedEvent.Sender;
DoMySearch(tb.Text);
});
As stated in the article (which is worth reading in full), this will fire the code in the lambda expression whenever half a second elapses without the user typing anything.
I'll clean the example up tomorrow when I'm in front of my development PC, but this should give you a starting point now.

- 3,409
- 22
- 25
-
Broken link (Rx Can Improve UI Responsiveness) – Dunc Dec 13 '12 at 14:17
Here's my working code based on Loren's input:
private void SearchTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (SearchTextBoxTimer != null)
{
Console.WriteLine("The user is currently typing.");
if (SearchTextBoxTimer.Interval < 750)
{
SearchTextBoxTimer.Interval += 750;
Console.WriteLine("Delaying...");
}
}
else
{
Console.WriteLine("The user just started typing.");
SearchTextBoxTimer = new System.Windows.Forms.Timer();
SearchTextBoxTimer.Tick += new EventHandler(SearchTextBoxTimer_Tick);
SearchTextBoxTimer.Interval = 500;
SearchTextBoxTimer.Start();
}
}
And the event handler:
private void SearchTextBoxTimer_Tick(object sender, EventArgs e)
{
Console.WriteLine("The user finished typing.");
if (SearchTextBox.Text == "")
{
ConsoleTextBox.Text = "Searching: All";
}
else
{
ConsoleTextBox.Text = "Searching: " + SearchTextBox.Text;
}
SearchTextBox_TextChanged();
SearchTextBoxTimer.Stop();
SearchTextBoxTimer.Dispose();
SearchTextBoxTimer = null;
}
If anyone plays with this code, let me know if you tweak the time intervals I put in. I don't think they are optimal quite yet.

- 27,280
- 43
- 127
- 177
-
1A bad idea--that Stop should be at the front of the procedure--what happens if a timer interval runs while you're doing the search?? I also think the timer should remain in existence, not be continually created and destroyed. – Loren Pechtel Jun 01 '10 at 23:17
Set a timer for the desired delay interval. Start the timer on the key up event. If the timer trips you stop the timer and run your search.
100ms is NOT a good interval, though!! That's about 100wpm even if the typing is absolutely even.

- 8,945
- 3
- 33
- 45
One suggestion is to not surprise the user. This is generally a good UI design principle. So only perform the actual search when the textbox loses focus. It is one thing to show incrementally matching search strings as a user types (like Google), but another to surprise the user with an unsolicited search after some keyboard delay. Personally I would find this irritating, as I often pause to think about a search string while entering it.

- 1,148
- 6
- 12
Here is a code sample to solve this
using System;
using System.Timers;
using System.Windows.Input;
using Timer = System.Timers.Timer;
namespace Example
{
public partial class OnKeyUpInputExample
{
// Timer set to elapse after 750ms
private Timer _timer = new Timer(750) { Enabled = false };
// Constructor
public OnKeyUpInputExample()
{
//What to do when _timer elapses
_timer.Elapsed += TextInput_OnKeyUpDone;
}
// Event handler
private void TextInput_OnKeyUp(object sender, KeyEventArgs e)
{
// You could also put the .Stop() in an OnKeyDown event handler if you need to account for keys being held down
_timer.Stop();
_timer.Start();
}
// Function to complement timer elapse
private void TextInput_OnKeyUpDone(object sender, ElapsedEventArgs e)
{
// If we don't stop the timer, it will keep elapsing on repeat.
_timer.Stop();
this.Dispatcher.Invoke(() =>
{
//Replace with code you want to run.
Console.WriteLine("KeyUp timer elapsed");
});
}
}
}

- 3,762
- 1
- 22
- 34
-
or `Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>` if on uwp, instead of Invoke – gattsbr Nov 02 '20 at 03:44
Some views can be found here: Delayed function calls
Record the timestamp of every keyup event, and use the Timer class to delay the execution of a method. Inside that method, you can consider whether the user has stopped typing, comparing the current time to the last keyup event timestamp. You could experiment with the interval, ensuring responsiveness. It's also smart to limit the hits, and only allow searches for a minimum of i.e. 3 characters.
Timer: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
-
The linked solution doesn't work for user input regarding keyup action. Using the above will cause a delay to occur, and then execute, so what will happen is if you type 5 key strokes, it will delay for x amount of time, then execute 5 times. – gattsbr Aug 15 '18 at 17:57