当我在 {{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>
答案 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),因此您不希望这样做。