簡體   English   中英

Thread.Sleep 凍​​結 UI

[英]Thread.Sleep freeze the UI

我知道,它已經來過很多次了,但我仍然不知道該怎么做。

我想創建一個程序,該程序會重復從數據庫中下載數據,因此用戶將看到程序中的數據到這個時候。

我不需要快速加載數據庫,所以我使用 sleep,但 sleep 會凍結整個 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 不會被凍結?

要定期做某事,您應該使用計時器。 如果您想要一個在 WPF UI 線程上觸發的計時器,請使用DispatcherTimer - 盡管您正在下載數據這一事實表明您應該異步執行此操作,或使用后台線程。 對於后者,您可以使用System.Threading.Timer

基本上,你應該阻止的時間顯著時期UI線程,正是因為它將會凍結您的UI。

調用startStopButton.Dispatcher.BeginInvoke意味着它將在 UI 線程上運行。 這確實意味着您的 UI 在調用該方法時會凍結,其中包含Thread.Sleep

我建議創建一個新Task並在那里執行您的代碼。 但是,您需要在與 UI 元素交互時調用InvokeBeginInvoke ,以防止跨線程 UI 操作。

Task.Run(CheckNextNumber);

為了不凍結 UI,您可以使用許多工具:

如果你猶豫,你可以閱讀C#/VB.Net Task vs Thread vs 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
                    }
                } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM