希望看看我是否可以在这方面获得一些帮助。我有一个后台工作人员,它将执行SQL查询,然后在进度更改事件期间更新Datagrid。但是,它跳过第一行,并将重复的最后一行添加到数据网格。列标题已关闭,因为我在UID中添加了此列以进行故障排除。因此,请忽略标题与数据不匹配的方式。 enter image description here
我检查了在IF中具有Read()的常见原因,但事实并非如此。
有趣的是,如果我在阅读器上稍作休息= Sqlcmd.ExecuteReader();并逐步执行,它会随机运行。
任何帮助将不胜感激!我完全不知所措。
-
另外,如果我可以将DGV添加项从进度更改更改为完成事件,那也将是巨大的好处。 enter image description here
/// DO WORK
private void issueBWworker_DoWork_1(object sender, DoWorkEventArgs e)
{
// DGV 1
RetriveTableData Obj = (RetriveTableData)e.Argument;
string SqlcmdString = "SELECT * FROM xBETA_OAP_ISSUE";
SqlDataReader reader;
int i = 1;
try
{
using (SqlConnection conn = new SqlConnection(ConnString))
{
Sqlcmd = new SqlCommand(SqlcmdString, conn);
conn.Open();
reader = Sqlcmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Obj.uid = reader["id"].ToString();
Obj.iss_type = reader["issue_type"].ToString();
Obj.inc_num = reader["ticket_num"].ToString();
Obj.create_date = reader["create_date"].ToString();
Obj.created_by = reader["created_by"].ToString();
Obj.active = reader["active"].ToString();
Obj.change_date = reader["change_date"].ToString();
Obj.changed_by = reader["changed_by"].ToString();
Thread.Sleep(100);
//MessageBox.Show(Obj.uid);
// To Report progress.x
issueBWworker.ReportProgress(i, Obj);
if (issueBWworker.CancellationPending)
{
// Set the e.Cancel flag so that the WorkerCompleted event
// knows that the process was cancelled.
e.Cancel = true;
issueBWworker.ReportProgress(0);
return;
}
i++;
}
conn.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// Progress Changes
private void issueBWworker_ProgressChanged_1(object sender, ProgressChangedEventArgs e)
{
if (!issueBWworker.CancellationPending)
{
// DGV 1
RetriveTableData Obj = (RetriveTableData)e.UserState;
issue_dgv.Rows.Add(Obj.uid.ToString(), Obj.iss_type.ToString(), Obj.inc_num.ToString(), Obj.create_date.ToString(), Obj.created_by.ToString(), Obj.active.ToString(), Obj.change_date.ToString(), Obj.changed_by.ToString());
pbar.Value = e.ProgressPercentage;
//toolStripStatusLabel1.Text = "Processing row.. " + e.ProgressPercentage.ToString() + " of " + TotalRecords;
}
}
/// Complete
private void issueBWworker_RunWorkerCompleted_1(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
//toolStripStatusLabel1.Text = "Cancelled by User Intentionally...";
pbar.Value = 0;
pbar.Visible = false;
}
// Check to see if an error occurred in the background process.
else if (e.Error != null)
{
//toolStripStatusLabel1.Text = e.Error.Message;
pbar.Visible = false;
}
else
{
// BackGround Task Completed with out Error
pbar.Visible = false;
//toolStripStatusLabel1.Text = " All Records Loaded...";
}
}
根据documentation,在备注部分中提到对ReportProgress
的调用是异步的,并立即返回。但是,为了使其能够按预期与代码一起工作,您需要使其同步运行。
这是因为您使用相同的对象Obj
,将阅读器的每次迭代中的数据传递给ReportProgress
-并可能使用Thread.Sleep(100)
作为同步手段-这实际上不是有效的或有效的设计,并可能导致您看到的行为。
例如,假设数据有四行,这将是结果:
+--------+-----------------------------------+--------------------------------------------+
| Thread | DoWork | ReportProgress |
+--------+-----------------------------------+--------------------------------------------+
| 1 | Populate values of Obj with row 1 | |
+--------+-----------------------------------+--------------------------------------------+
| 2 | Wait 100 ms | |
+--------+-----------------------------------+--------------------------------------------+
| 3 | Dispatch ReportProgress | |
+--------+-----------------------------------+--------------------------------------------+
| 4 | Populate values of Obj with row 2 | |
+--------+-----------------------------------+--------------------------------------------+
| 5 | Wait 100 ms | Add a row with values of Obj, now at Row 2 |
+--------+-----------------------------------+--------------------------------------------+
| 6 | Dispatch ReportProgress | |
+--------+-----------------------------------+--------------------------------------------+
| 7 | Populate values of Obj with row 3 | |
+--------+-----------------------------------+--------------------------------------------+
| 8 | Wait 100 ms | Add a row with values of Obj, now at Row 3 |
+--------+-----------------------------------+--------------------------------------------+
| 9 | Dispatch ReportProgress | |
+--------+-----------------------------------+--------------------------------------------+
| 10 | Populate values of Obj with row 4 | |
+--------+-----------------------------------+--------------------------------------------+
| 11 | Wait 100 ms | Add a row with values of Obj, now at Row 4 |
+--------+-----------------------------------+--------------------------------------------+
| 12 | Dispatch ReportProgress | |
+--------+-----------------------------------+--------------------------------------------+
| 13 | End of iteration, no more rows | Add a row with values of Obj, now at Row 4 |
+--------+-----------------------------------+--------------------------------------------+
[从另一个站点,我发现了一些有用的东西。似乎reader.Read()可以跳过第一行。https://forums.asp.net/t/1124375.aspx?sqldatareader+reads+from+second+row+skip+the+first+row+和https://bytes.com/topic/asp-net/answers/311487-sqldatareader-skipping-first-row-loop
if ((reader.Read == false))
{
//do something here;
}
else
{
do
{
hinfo.Name = reader["_name"].ToString();
hi.Add(hinfo);
}
while (reader.Read());
}
从那篇文章看来,reader.Read()看着第一行,然后在第二行开始处理。我希望这有帮助。我有完全符合您原始要求的代码,并且正在使用FWIW。 (在这里Datareader not displaying first row接受)