![](/img/trans.png)
[英]Can calling Thread.Sleep(n) from a Task off the UI thread freeze the 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 元素交互時調用Invoke
或BeginInvoke
,以防止跨線程 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.