【发布时间】:2019-11-02 06:09:01
【问题描述】:
编辑:使用此解决:http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/
在我的项目(.net/windows 表单)中,我正在用一个大的DataTable 填写DataGridView。填充可能需要 20 秒,所以我想要一个动画加载窗口。如果线程忙,此动画将冻结,因此我必须为窗口或填充 DataGridView 使用新线程。
我尝试使用BackgroundWorker 来显示表单,但它会是一个正确形状的空白窗口。
我也尝试使用BackgroundWorker 来填充DataGridView,但它会抛出一个错误,指出DataGridView 正在由与创建它的线程不同的线程访问。由于 DataGridView 是在设计器类中创建的,所以我不能只在新线程中创建它——而且该解决方案听起来不太优雅。
在填写DataGridView 时,对我来说,展示一个有效的动画表单的最佳方式是什么?
编辑:答案并没有为我解决问题,所以我尝试将代码分解为可以在此处呈现的内容。我以前没有这样做,因为它看起来并没有足够的相关性来处理大约 1k 行代码。此处提供的代码中可能缺少某些内容或先前实验的一些残留物。请忽略函数的错误命名,这是一个遗留问题,一旦我开始工作,我会修复它。部分代码是古老的。
我让它运行没有错误,但是 frmLoading 仍然没有动画(如果我在工作线程不忙的时候让它保持活动状态)。
namespace a
{
public partial class frmMain : DockContent, IPlugin
{
//...
private delegate void SafeCallDelegate(DataTable dt);
private Thread thread1 = null;
private frmLoading frmLoading = new frmLoading();
public frmMain()
{
//...
}
//...
private void FillDataGrid(DataTable dt)
{
if(this.InvokeRequired)
{
var d = new SafeCallDelegate(FillDataGrid);
Invoke(d, new object[] { dt });
}
else
{
//...
DataGridFiller(dt);
}
}
private void DataGridFiller(DataTable dt)
{
BindingSource dataSource = new BindingSource(dt, null);
//...
dgvData.DataSource = dataSource;
//...
frmLoading.Hide();
}
private void btnGetData_Click(object sender, EventArgs e)
{
DataTable dt = [...];
// Wenn Daten vorhanden sind, dann anzeigen
if (dt != null)
{
//...
frmLoading.Show();
thread1 = new Thread(() => FillDataGrid(dt));
thread1.Start();
}
}
}
}
【问题讨论】:
-
查看 Microsoft 提供的任务并行库。它的 async/await 模式正是您所需要的。
-
我们需要看代码。
-
即使您的问题已经有了答案(使用 BackgroundWorker 和 Control.Invoke),在您的问题中提供代码示例总是有意义的。例如,如果慢速部分是一个 IO 调用,那么如果您的 .NET Framework 版本支持,自然会使用 async / await 进行此类调用。
-
是的,我刚才正在处理这个问题。以前没有这样做,因为它似乎真的没有必要(而且这是一堆工作),但是即使尝试了解决方案仍然存在问题。
-
@Infrisios 我编辑了我的答案,希望您现在可以解决您的问题。问候
标签: c# .net multithreading winforms backgroundworker