Reputation: 45
I have a text block called "findListText". Here, I am updating the text in it:
private void InstantSearch(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
HitEnter = true;
}
findListText.Text = "Processing request. Please wait...";
Find(bool.Parse("False" as string));
}
However, the next set of code is a search function that can take up to 10 seconds, and at the end of it, it changes the text in findListText again.
private void Find(bool? bForward = true)
{
{
//Lots and lots of code
}
findListText.Text = "Search completed."
}
The problem is, the textblock never seems to update to "Processing request. Please wait...". The textblock is in it's original state and 10 seconds later updates to "Search completed.", seemingly skipping out the middle man.
I'm using C# - WPF. What am I doing wrong here?
Upvotes: 3
Views: 7684
Reputation: 45
I came back to this just now, and had another browse across the internet for similar problems. For something as simple as pushing a single message before a long running process occurs, I'm surprised no-one suggested "Application.DoEvents();". Yes, I know it has it's flaws, and my UI will still hang, but this suits me perfectly for my situation, at least.
Upvotes: 0
Reputation: 5282
Doesn't matter what technology I think.
The code is running on the same thread, meaning the the UI won't be updated untill all the code on that thread is completed. You should address a different thread to update that textblock.
In that case, you will have 2 thread:
I've created a little something that should resolve your problem, it's based on this Stack Overflow page
Upvotes: 4
Reputation: 5851
You should look into the UI threading concept of WPF. Invoke the Dispatcher
to modify the textbox. Also the search should run with ThreadPool.QueueWorkerItem
.
// Start worker thread
ThreadPool.QueueUserWorkItem(state =>
{
// Long running logic here
findListText.Dispatcher.BeginInvoke(() => findListText.Text = "Processing request. Please wait...");
Find(bool.Parse("False" as string));
// Tip: Run change on GUI thread from the worker using the dispatcher
findListText.Dispatcher.BeginInvoke(() => findListText.Text = "Search completed.");
});
Upvotes: 1
Reputation: 1827
Here is how to run your find method in its own thread.
private void InstantSearch(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
HitEnter = true;
}
findListText.Text = "Processing request. Please wait...";
BackgroundWorker tempWorker = new BackgroundWorker();
tempWorker.DoWork += delegate
{
Find(bool.Parse("False" as string));
};
tempWorker.RunWorkerAsync();
}
If you try that, you'll get an error because you access your UI thread from the background thread. So you'll need to update your find method as well.
private void Find(bool? bForward = true)
{
{
//Lots and lots of code
}
Dispatcher.BeginInvoke((Action) delegate {
findListText.Text = "Search completed."
});
}
Upvotes: 1
Reputation: 7692
Since this is WPF, try the following: after changing the text to "Processgin", call:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { this.UpdateLayout(); }));
This will tell the thread to update the UI as soon as possible.
Upvotes: 2