当我查询数据库并更新 BackgroundWorker
中 DoWork
中的DataGrid
时,我试图使不确定的ProgressBar
动画平稳运行.我了解我无法在 DoWork
中更新UIThread,因此我使用Dispatcher.BeginInvoke
访问DataGrid
,但是我仍然收到由另一个线程拥有的异常.
I am trying to keep my indeterminate ProgressBar
animation running smoothly as I query database and updating DataGrid
in DoWork
in BackgroundWorker
. I understand that I cannot update UIThread in DoWork
, so I use Dispatcher.BeginInvoke
to access DataGrid
, yet I still receive the owned-by-another-thread exception.
问题1
为什么会这样? DoWork应该处于开启状态 UIThread和Dispatcher拥有的BackgroundWorker线程 允许我的DoWork访问我的GUI.
Why is this happening? DoWork should be on BackgroundWorker's thread owned by UIThread, and Dispatcher should allow my DoWork to access my GUI.
进一步查看BackgroundWorker,建议UI操作应在 ProgressChanged()
中处理.但是,如果我将所有数据库/GUI操作移至 ProgressChanged()
并将Thread.Sleep(5000)
放在 DoWork()
上,以模拟需要处理的内容,从而为留出足够的时间> ProgressChanged()
运行,尽管ProgressBar
继续其不确定的平滑动画,但GUI尚未更新.
Looking further into BackgroundWorker suggest UI operation should be handled in ProgressChanged()
. But if I move all database/GUI operation to ProgressChanged()
and put a Thread.Sleep(5000)
on DoWork()
to emulate something to work on to lend enough time for ProgressChanged()
to run, the GUI is not being updated, although the ProgressBar
continue its indeterminate smooth animation.
问题2
我在BackgroundWorker线程上调用了Thread.Sleep(5000). ProgressChanged()应该花5秒钟查询数据库,然后 更新GUI.为什么不呢?
I called a Thread.Sleep(5000) on BackgroundWorker thread. ProgressChanged() should spend 5 seconds querying database and updating GUI. Why not?
XAML:
<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>
C#
private BackgroundWorker bgw = new BackgroundWorker();
private void btnSearch_Click(object sendoer, RoutedEventArgs e)
{
bgw.WorkerReportsProgress = true;
bgw.ProgressChanged += ProgressChanged;
bgw.DoWork += DoWork;
bgw.RunWorkerCompleted += BGW_RunWorkerCompleted;
bgw.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
// Thread.Sleep(5000);
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())
{
Dispatcher.BeginInvoke(new Action(() =>
{
myDataGrid.Items.Add(new
{
Id = rdr.GetInt32(0),
Name = rdr.GetString(1).ToString(),
});
}));
}
}
}
}
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Paste code from DoWork and uncomment Thread.Sleep(5000)
}
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}