在做开发的时候,经常需要加载数据,当数据量很大的时候,一次性加载可能会造成卡机的现象,这是我们可以通过BackgroundWorker在后台执行,并把需要更新的数据更新到UI,这样就不会因为数据过多,加载时间太久而至于卡死
下面说说用法
BackgroundWorker类有几个重要的方法和事件
事件: DoWork 当调用RunWorkerAsync时执行,处理后台任务
ProgressChanged 用于更新进度和UI
RunWorkerCompleted 后台任务完成时执行
属性: WorkerSupportsCancellation 是否支持异步取消
WorkerReportsProgress 是否报告进度更新,如果需要更新UI,则必须设置为true
方法:RunWorkerAsync 开启后台任务
1、创建后台任务
BackgroundWorker bw = new BackgroundWorker(); //设置为类的成员,让其他函数可以访问 bw.WorkerSupportsCancellation = true; bw.WorkerReportsProgress = true; bw.DoWork += new DoWorkEventHandler(Dowork); bw.ProgressChanged += new ProgressChangedEventHandler(Progress); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Complete);
bw.RunWorkerAsync();
2、下面是四个事件函数
首先先声明一个类,用于数据绑定
public class Items { public Items(string title, string artist) { this.Title = title; this.Artist = artist; } public string Title { get; set; } public string Artist { get; set; } }
然后设置ListBox绑定数据
<ListBox Name="listBox1" Margin="0,0,-12,0"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="0,0,0,17" Width="432" Height="78"> <TextBlock Text="{Binding Title}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding Artist}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
在这里我是在后台加载媒体中的的音乐,当调用 CancelAsync() 函数取消后台任务时,会把CancellationPending属性设置为true
public void Dowork(object sender, DoWorkEventArgs e) { MediaLibrary library = new MediaLibrary(); foreach (Song song in library.Songs) { if (worker.CancellationPending) //判断是否异步取消了后台任务,如果异步取消,则直接返回 return; bw.ReportProgress(10, new Items(song.Name, song.Artist.Name)); //把当前的进度报告出去,会调用Progress()函数更新UI Thread.Sleep(100); //当更新过快时,可以适当的休眠 } }
这里在更新UI的时候最好调用Thread.Sleep(),因为当UI更新过快的时候,也会出现卡顿的情况,所以最好使线程休息后在继续更新
在Progress函数中更新UI
public void Progress(object sender, ProgressChangedEventArgs e) { Items item = e.UserState as Items; this.listBox1.Items.Add(item); }
public void Complete(object sender, AsyncCompletedEventArgs e) { MessageBox.Show("加载完成"); }
当需要加载大量的数据的时候,可以先加载一小部分,其他的交给后台来做,这样就不会出现长时间的卡机状态