Honza Kalina
Honza Kalina

Reputation: 183

Thread.Sleep freeze the UI

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

Answers (4)

Honza Kalina
Honza Kalina

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

jd6
jd6

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

Patrick Hofman
Patrick Hofman

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

Jon Skeet
Jon Skeet

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

Related Questions