1.使用定時器異步修改
這是相對比較簡單的方法
在Wpf中定時器使用DiapatcherTimer,不使用Timer原因:
在一個應用程序中,Timer會重復生成time事件,而DispatcherTimer是一個集成到了Dispatcher隊列中的時鍾,這可以使它被按照指定的時間間隔以指定的priority定期執行。
對於一個Timer時鍾事件,系統並不能保證在時間間隔到達后被立即執行,但是能夠確保在時間間隔到達之前不被執行。這是因為DispatcherTimer像其他操作一樣被放置在了Dispatcher隊列中。何時執行DispatcherTimer事件依賴於隊列中的其他任務以及他們的優先級.
如果一個WPF應用程序使用了Timer時鍾,那么它的事件必須在一個單獨的時鍾線程中運行,而不是在UI線程中,這對於WPF應用程序毫無用處——你沒法在UI線程之外直接訪問UI元素,而只能通過Invoke或者BeginInvoke將操作發送給Dispatcher 對象,委托Dispatcher去執行UI操作。
看到這里,你大概知道了為什么我們在WPF中應該用DispatcherTimer而不是Timer了:DispatcherTimer與Dispatcher運行於同一個線程中——UI線程,而且具有相同的DispatcherPriority優先級。
實例:
Xaml代碼:
<Grid> <TextBox x:Name="textBox" Padding="10" Height="45" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Margin="10,105,10,0"/> </Grid>
后台代碼:
//啟動其他線程處理,調用失敗 //Task.Run(()=> { // DispatcherTimerHelper.DoWork(textBox); //}); //主線程調用成功 DispatcherTimerHelper.DoWork(textBox);
public class DispatcherTimerHelper { //定時器,在指定事件內重復執行 //在非主線程中,會出現異常,當前線程結束 static DispatcherTimer _timer = new DispatcherTimer(); public static void DoWork(TextBox textBlock) { _timer.Interval = new TimeSpan(0, 0, 1); EventHandler event1 = new EventHandler(timer_Tick); _timer.Tick += event1; _timer.Tag = textBlock; _timer.Start(); } public static void Stop() { _timer.Stop(); } static void timer_Tick(object sender, EventArgs e) { DispatcherTimer timer = sender as DispatcherTimer; TextBox box = timer.Tag as TextBox; box.Text = "張三"+DateTime.Now; } }
2.使用BackgroundWorker
這個類是專門用於簡化Windows Form程序與線程相關的問題設計的,同樣適用於WPF程序.適合於一個長期的后台進程,支持進度通知,取消支持,完成通知等功能.
使用方法也很簡單,創建一個BackfruopWorker實例,它有幾個事件.
DoWork事件會在另外一個線程中執行,用RunWorkerAsync()啟動.所以在這個事件中不要去處理修改界面的事情
RunWorkerCompleted事件,在DoWork事件返回時(正常或者異常返回),在圖形的線程中執行,所以可以修改界面
ProgressChanged事件,使用ReportProgress()方法調用,同時是在圖形界面的線程中執行,通常負責修改一下進度條什么的.而ReportProgress()方法,通常會在DoWork的事件中調用,然后給一個百分比的值.要使用這個功能,需要把WorkerReportsProgress屬性設置成true
另外值得一說的是,要取消支持需要把WorkerSupportsCancellation屬性設為true,使用CancelAsync()方法調用,但是這個調用不會終止進程,所以在DoWork事件中需要判斷CancellationPending.
實例:
Xaml代碼:
<StackPanel> <ProgressBar Name="progressBar" Height="20" Width="200" Margin="10,80,20,10"></ProgressBar> <Button Name="btnProcess" Width="100" Click="btnProcess_Click" Margin="5">開始后台任務</Button> <Button Name="btnCancel" Width="100" Click="btnCancel_Click" Margin="5">取消后台任務</Button> <Label x:Name="label" Content="Label" Margin="10"/> </StackPanel>
C#后台代碼:

/// <summary> /// Thread9.xaml 的交互邏輯 /// </summary> public partial class Thread9 : Window { BackgroundWorker bgWorker = new BackgroundWorker(); public Thread9() { InitializeComponent(); bgWorker.WorkerReportsProgress = true; bgWorker.WorkerSupportsCancellation = true; //執行任務代碼 bgWorker.DoWork += DoWork_Handler; //執行過程觸發 bgWorker.ProgressChanged += ProgressChanged_Handler; //執行結束,或有異常結束觸發 bgWorker.RunWorkerCompleted += RunWorkerCompleted_Handler; } private void btnProcess_Click(object sender, RoutedEventArgs e) { //開始執行 if (!bgWorker.IsBusy) { bgWorker.RunWorkerAsync(); } } private void ProgressChanged_Handler(object sender, ProgressChangedEventArgs args) { //在過程改變事件中可以修改UI內容 progressBar.Value = args.ProgressPercentage; label.Content = "ProgressChanged方法執行完成" + args.ProgressPercentage; } private void DoWork_Handler(object sender, DoWorkEventArgs args) { //在DoWork中修改UI同樣會拋出異常 //label.Content = "DoWork方法執行完成"; BackgroundWorker worker = sender as BackgroundWorker; for (int i = 1; i <= 100; i++) { if (worker.CancellationPending) { args.Cancel = true; break; } else { //手動觸發觸發過程,代碼執行 worker.ReportProgress(i); Thread.Sleep(100); } } } private void RunWorkerCompleted_Handler(object sender, RunWorkerCompletedEventArgs args) { progressBar.Value = 0; if (args.Cancelled) { MessageBox.Show("后台任務已經被取消。", "消息"); } else { MessageBox.Show("后台任務正常結束。", "消息"); } } private void btnCancel_Click(object sender, RoutedEventArgs e) { //結束執行 bgWorker.CancelAsync(); } }