BackgroundWorker读取数据库并更新GUI

时间:2017-06-07 09:51:50

标签: c# wpf backgroundworker

当我在 {{1}中查询数据库并更新 ProgressBar 中的DataGrid时,我试图保持我的不确定DoWork动画顺利运行} 即可。我知道我无法在 BackgroundWorker 中更新UIThread,因此我使用DoWork访问Dispatcher.BeginInvoke,但我仍然收到了由另一个线程拥有的异常

  

问题1

     

为什么会这样? DoWork应该开启   BackgroundWorker的线程由UIThread和Dispatcher拥有   允许我的DoWork访问我的GUI。

进一步了解BackgroundWorker建议应该在 DataGrid 中处理UI操作。但是,如果我将所有数据库/ GUI操作移至 ProgressChanged() 并将ProgressChanged()放在 Thread.Sleep(5000) 上以模拟要处理的内容为 DoWork() 提供足够的时间来运行,尽管ProgressChanged()继续其不确定的平滑动画,但GUI仍未更新。

  

问题2

     

我在BackgroundWorker线程上调用了Thread.Sleep(5000)。   ProgressChanged()应该花5秒查询数据库和   更新GUI。为什么不呢?

XAML:

ProgressBar

C#

<DataGrid x:Name="myDataGrid" ScrollViewer.CanContentScroll="True" 
          EnableRowVirtualization="True" EnableColumnVirtualization="True"
          VirtualizingPanel.IsContainerVirtualizable="True" 
          VirtualizingPanel.IsVirtualizing="True"
          VirtualizingPanel.IsVirtualizingWhenGrouping="True"
          Height="500" MaxHeight="500" />

<ProgressBar x:Name="myProgressBar" Height="20" Width="400"
             IsIndeterminate="True" Visibility="Visible" />

<Button x:Name="mySearch" Click="btnSearch_Click">Search</Button>

1 个答案:

答案 0 :(得分:1)

DoWork事件处理程序中创建项集合,然后在完成后在ItemsSource事件处理程序中将DataGrid的{​​{1}}属性设置为此属性在后台线程上获取数据:

RunWorkerCompleted

您需要调用private void btnSearch_Click(object sendoer, RoutedEventArgs e) { bgw.WorkerReportsProgress = true; bgw.ProgressChanged += ProgressChanged; bgw.DoWork += DoWork; bgw.RunWorkerCompleted += BGW_RunWorkerCompleted; myProgressBar.Visibility = Visibility.Visible; bgw.RunWorkerAsync(); } private void DoWork(object sender, DoWorkEventArgs e) { List<object> results = new List<object>(); using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("SELECT * FROM " + MyTableName, conn)) { using (SqlDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { results.Add(new { Id = rdr.GetInt32(0), Name = rdr.GetString(1).ToString(), }); } } } } e.Result = results; } private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { myDataGrid.ItemsSource = e.Result as List<object>; myProgressBar.Visibility = Visibility.Collapsed; } 的{​​{1}}方法来报告任何进度,但是报告数据库检索操作的进度是没有意义的,因为您无论如何都不知道实际的进度。你最好只使用一个不确定的ReportProgress并在开始操作时显示它,并在操作完成后隐藏它,如上面的示例代码所示。

BackgroundWorker将阻止当前线程。如果您阻止UI线程,则无法更新您的UI(包括ProgressBar),因此您不希望这样做。