[英]using backgroundworker in Winforms (C#) with MVP pattern
[英]Using BackgroundWorker to refresh datagrid in winforms C#
我在使用后台工作程序线程来获取数据和更新数据网格的表单时遇到问题。
用例是带有进度条的列表,该进度条显示了数据库中已装入多少表。
它按以下顺序进行,
有时它可以很好地工作,但是其他FormB.ShowDialog()
会返回带有空引用异常。 我不明白为什么。
这是呼叫表单代码:
private void button1_Click(object sender, EventArgs e)
{
using (var f = new FormFactProgress(_dwConnectionString, _sourceConnectionString, _etlConnectionString))
{
f.ShowDialog(); \\ THIS IS WHERE THE NULL REFERENCE EXCEPTION ALWAYS HAPPENS!
labelLoadWarning.Visible = false;
groupBoxLoadFacts.Enabled = false;
buttonLoadFacts.BackColor = Color.FromArgb(128, 255, 128);
buttonLoadFacts.Text = "Loaded";
if (dynamicWarehouseCatalog.FactsLoaded(_dwConnectionString) && dynamicWarehouseCatalog.DimsLoaded(_dwConnectionString))
{
groupBoxSync.Enabled = true;
}
}
}
子窗体(这是第二个进行datagrid更新的背景工作人员):
private void buttonStart_Click(object sender, EventArgs e)
{
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
if (!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
backgroundWorker2.DoWork += new DoWorkEventHandler(backgroundWorker2_DoWork);
if (!backgroundWorker2.IsBusy)
{
backgroundWorker2.RunWorkerAsync();
}
buttonStart.Enabled = false;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
BackgroundWorker worker = (BackgroundWorker)sender;
sSISDBCatalog.StartFactLoad(_etlConnectionString);
while (isLoading)
{
System.Threading.Thread.Sleep(1000);
if (dynamicWarehouseCatalog.FactsLoaded(_dwConnectionString))
{
if (dynamicWarehouseCatalog.AllFactsLoaded(_dwConnectionString))
{
isLoading = false;
}
}
}
}
catch(Exception ex)
{
MessageBox.Show(
"Progress viewing has failed. The ETL is still running though. Please monitor your data warehouse growth manually. Error: " + ex, "Pregress Visualisation Failed",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
try
{
Control.CheckForIllegalCrossThreadCalls = false;
BackgroundWorker worker = (BackgroundWorker)sender;
var dw = DwData(_dwConnectionString);
var source = SourceData(_sourceConnectionString);
dataGridView1.DataSource = GetProgress(dw, source);
while (isLoading)
{
System.Threading.Thread.Sleep(1000);
dw = DwData(_dwConnectionString);
dataGridView1.DataSource = GetProgress(dw, source);
dataGridView1.Refresh();
}
MessageBox.Show(
"Your data warehouse facts are loaded!", "Facts Loaded",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
catch (Exception ex)
{
MessageBox.Show(
"Progress viewing has failed. The ETL is still running though. Please monitor your data warehouse growth manually. Error: " + ex, "Pregress Visualisation Failed",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
您应该使用BackgroundWorker.ReportProgress Method (Int32, Object)
如图所示文档这里 。 我始终使用第二个参数传递一个enum
以标识从哪个后台工作人员报告了此进度。 您可以使用类似的方法。
所以我找到了一个很好的解决方案。 基本上,我将后台工作程序更改为获取数据的任务,然后调用需要更新的dataGridView。 例如
Task.Factory.StartNew(() =>
UpdateUI());
将后台工作人员重命名为UpdateUI以及内部:
var dw = DwData(_dwConnectionString);
var source = SourceData(_sourceConnectionString);
DataTable prog;
while (isLoading)
{
System.Threading.Thread.Sleep(1000);
dw = DwData(_dwConnectionString);
if (dw.Rows.Count > 0)
{
prog = GetProgress(dw, source);
if (prog.Rows.Count > 0)
{
dataGridView1.Invoke(new MethodInvoker(() => { dataGridView1.DataSource = prog; dataGridView1.Refresh(); }));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.