Reputation: 67
I have an issue with the WPF usage with loops and frozen screen. my example code is here
private void Btn1_OnClick(object sender, RoutedEventArgs e)
{
ThreadPool.QueueUserWorkItem(
o =>
{
FaturaCount.Dispatcher.InvokeAsync(() =>
{
int a = 0;
for (int i = 0; i < 10000000000; i++)
{
a = a + i;
}
txtCount.Text = a.ToString();
}, DispatcherPriority.Background);
});
}
the screen freezes while the loop continues. I want to make loop work at back and the screen still be used until it finished. Why is happening and how can i fix this?
Upvotes: 1
Views: 1308
Reputation: 37059
When you "invoke into a thread", you're telling that thread to stop whatever it's doing and execute your code instead.
So you're starting a thread which promptly blocks the UI thread while it does all of its work there. That wasn't your intent.
Instead of putting the entire loop in the Invoke lambda, just invoke for the one tiny little part where you need to touch the UI:
ThreadPool.QueueUserWorkItem(
o =>
{
int a = 0;
for (int i = 0; i < 10000000000; i++)
{
a = a + i;
FaturaCount.Dispatcher.Invoke(() =>
{
txtCount.Text = a.ToString();
});
}
});
Clearly, the above code doesn't do anything useful, and such rapid repeated calls to Invoke don't make much sense. That'll tie up the UI very nearly as badly as your original version. Modern hardware can increment integers and iterate loops very, very quickly. Is this your actual code, or is the loop in the thread actually doing something more useful, with longer intervals between UI updates? If I were implementing a thread that just displayed an incrementing integer in a TextBlock, I'd put a Thread.Sleep(250) or something in the loop outside the Invoke. Give the UI a chance to respond to user input.
Or, much, much better yet, since this is WPF, write a viewmodel and update txtCount.Text
via a binding, which will do the invoke for you. You won't even have to think about the dispatcher then.
Upvotes: 2