简体   繁体   English

Thread.Sleep 冻​​结 UI

[英]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.我不需要快速加载数据库,所以我使用 sleep,但 sleep 会冻结整个 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?这段代码应该如何才能运行进程并且 UI 不会被冻结?

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.如果您想要一个在 WPF UI 线程上触发的计时器,请使用DispatcherTimer - 尽管您正在下载数据这一事实表明您应该异步执行此操作,或使用后台线程。 For the latter, you could use System.Threading.Timer .对于后者,您可以使用System.Threading.Timer

Basically you should never block the UI thread for significant periods of time, precisely because it will freeze your UI.基本上,你应该阻止的时间显著时期UI线程,正是因为它将会冻结您的UI。

Calling startStopButton.Dispatcher.BeginInvoke means it will run on the UI thread.调用startStopButton.Dispatcher.BeginInvoke意味着它将在 UI 线程上运行。 That indeed means your UI freezes when calling that method, with Thread.Sleep in it.这确实意味着您的 UI 在调用该方法时会冻结,其中包含Thread.Sleep

I suggest to create a new Task and execute your code in there.我建议创建一个新Task并在那里执行您的代码。 You need to call Invoke or BeginInvoke when interacting with UI elements though, to prevent cross-thread UI operations.但是,您需要在与 UI 元素交互时调用InvokeBeginInvoke ,以防止跨线程 UI 操作。

Task.Run(CheckNextNumber);

Not to freeze the UI, you can use many tools :为了不冻结 UI,您可以使用许多工具:

If you hesitate, you can read C# / VB.Net Task vs Thread vs BackgroundWorker .如果你犹豫,你可以阅读C#/VB.Net Task vs Thread vs BackgroundWorker

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
                    }
                } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM