0

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?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Honza Kalina
  • 173
  • 1
  • 1
  • 8

4 Answers4

4

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

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);
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
1

Not to freeze the UI, you can use many tools :

If you hesitate, you can read C# / VB.Net Task vs Thread vs BackgroundWorker.

Community
  • 1
  • 1
jd6
  • 429
  • 3
  • 9
0

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
                    }
                } 
Honza Kalina
  • 173
  • 1
  • 1
  • 8