Reputation: 183
I know, it's been here many times, but I still don't know how to do it.
I want to create a program that will repeatedly download data from database, so the user will see the data in the program to this time.
I do not need to load the database quickly, so I use sleep, but sleep freeze whole UI.
I take simple example.
<Window x:Class="ThreadingPrimeNumberSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Prime Numbers" Width="760" Height="500">
<Grid>
<Button Content="Start"
Click="StartOrStop"
x:Name="startStopButton"
Margin="10,10,693,433"
/>
<TextBlock Margin="87,15,547,424"><Run Text="Biggest Prime Found:"/><InlineUIContainer>
</InlineUIContainer></TextBlock>
<TextBlock x:Name="bigPrime" Margin="222,15,409,428"><Run Text="3"/></TextBlock>
<TextBox Height="104" TextWrapping="Wrap" Text="TextBox" Width="522" Margin="87,295,143,70"/>
</Grid>
</Window>
...usings...
namespace ThreadingPrimeNumberSample
{
public partial class MainWindow : Window
{
public delegate void NextPrimeDelegate();
//Current number to check
private long num = 3;
private bool continueCalculating = false;
public MainWindow()
: base()
{
InitializeComponent();
}
private void StartOrStop(object sender, EventArgs e)
{
if (continueCalculating)
{
continueCalculating = false;
startStopButton.Content = "Resume";
}
else
{
continueCalculating = true;
startStopButton.Content = "Stop";
startStopButton.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new NextPrimeDelegate(CheckNextNumber));
}
}
public void CheckNextNumber()
{
// Reset flag.
NotAPrime = false;
for (long i = 3; i <= Math.Sqrt(num); i++)
{
if (num % i == 0)
{
// Set not a prime flag to true.
NotAPrime = true;
break;
}
}
// If a prime number.
if (!NotAPrime)
{
bigPrime.Text = num.ToString();
}
num += 2;
Thread.Sleep(500);
if (continueCalculating)
{
startStopButton.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.SystemIdle,
new NextPrimeDelegate(this.CheckNextNumber));
}
}
private bool NotAPrime = false;
}
}
If was process started and I writing to the textbox or doing something... whole is it freezes.
How should this code look to be able to run the process and UI won't be frozen?
Upvotes: 0
Views: 1595
Reputation: 183
I have it:
newtheard(); // This start new theard with loading form database
public void newtheard()
{
Thread thread = new Thread(new ThreadStart(this.ReadFromMysql);
thread.IsBackground = true;
thread.Name = "My Worker.";
thread.Start();
}
public void ReadFromMysql()
{
while (true)
{
Thread.Sleep(800);
try
{
// some mysql reader
}
}
Upvotes: 0
Reputation: 429
Not to freeze the UI, you can use many tools :
If you hesitate, you can read C# / VB.Net Task vs Thread vs BackgroundWorker.
Upvotes: 1
Reputation: 157098
Calling startStopButton.Dispatcher.BeginInvoke
means it will run on the UI thread. That indeed means your UI freezes when calling that method, with Thread.Sleep
in it.
I suggest to create a new Task
and execute your code in there. You need to call Invoke
or BeginInvoke
when interacting with UI elements though, to prevent cross-thread UI operations.
Task.Run(CheckNextNumber);
Upvotes: 1
Reputation: 1503290
To do something periodically, you should use a timer. If you want a timer which fires on the WPF UI thread, use DispatcherTimer
- although the fact that you're downloading data suggests that you should either be doing that asynchronously, or using background threads. For the latter, you could use System.Threading.Timer
.
Basically you should never block the UI thread for significant periods of time, precisely because it will freeze your UI.
Upvotes: 4