线程.睡眠冻结UI

本文关键字:UI 冻结 线程 | 更新日期: 2023-09-27 18:27:44

我知道,它在这里已经很多次了,但我仍然不知道如何做到。

我想创建一个程序,重复从数据库下载数据,这样用户就可以在这个时候看到程序中的数据。

我不需要快速加载数据库,所以我使用睡眠,但睡眠冻结了整个UI。

我举一个简单的例子。

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

        }

    }

如果这个过程开始了,我在文本框里写东西或做什么。。。它冻结了。

这个代码应该如何才能运行流程并且UI不会被冻结?

线程.睡眠冻结UI

要定期执行某些操作,应该使用计时器。如果您想要一个在WPF UI线程上触发的计时器,请使用DispatcherTimer——尽管下载数据的事实表明您应该异步执行,或者使用后台线程。对于后者,可以使用System.Threading.Timer

基本上,您应该永远不要在相当长的一段时间内阻塞UI线程,正是因为它会冻结您的UI。

调用startStopButton.Dispatcher.BeginInvoke意味着它将在UI线程上运行。这确实意味着您的UI在调用该方法时会冻结,其中包含Thread.Sleep

我建议创建一个新的Task并在其中执行您的代码。不过,在与UI元素交互时,您需要调用InvokeBeginInvoke,以防止跨线程的UI操作。

Task.Run(CheckNextNumber);

为了不冻结UI,可以使用许多工具:

  • 线程:http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.90).aspx
  • 具有async和wait的任务:http://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx
  • BackgroundWorker:如何使用WPF后台工作程序

如果您有犹豫,可以阅读C#/VB.Net任务与线程与BackgroundWorker。

我有它:

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