问题描述
公司测试给出了一个bug,说是界面上的表点击后加载订单窗体会显示DBNull到Integer的转换错误。异常位置很明确,是从 DataGridView.CurrentRow.Cells("MID").Value 读取值并赋给 Integer 时抛出的。第一反应是数据问题,但数据库中该字段并不存在 NULL,而且问题并非必现,导致排查变得非常困难。
复现过程
经过多次调试,我发现一个非常诡异的现象:在鼠标双击表格行之后订单窗体真正加载完成之前DataGridView 的 选中行居然会随着鼠标最终停留的位置发生变化。也就是说:我明明是双击了某一条有效数据行,但代码真正去读 CurrentRow 时,它已经漂移到了 DataGridView 默认的最后一行空行。这一行的单元格值,自然是 DBNull,于是就触发了异常。
排查方法、解决方案
If blnInputInfo = False ThenblnInputInfo = Trueg_frmInputInfo = New frmInputInfog_frmInputInfo.MdiParent = g_frmMaing_frmInputInfo.Show()End IfShowChildform(g_frmInputInfo)'If (currentDgv.Name = "dgvDetail") Theng_frmInputInfo.clsAll()g_frmInputInfo.intMID = Me.dgvDetail.CurrentRow.Cells("MID").Valueg_frmInputInfo.txtID.Text = Me.dgvDetail.CurrentRow.Cells("制作单号").Valueg_frmInputInfo.readInfo()ElseIf currentDgv.Name = "dgvRedoDetail" Theng_frmInputInfo.clsAll()g_frmInputInfo.intMID = Me.dgvRedoDetail.CurrentRow.Cells("MID").Valueg_frmInputInfo.txtID.Text = Me.dgvRedoDetail.CurrentRow.Cells("制作单号").Valueg_frmInputInfo.readInfo()End If
这个窗体加载过程中是没有将耗时操作放在异步方法里的,这样来说界面还能响应外设的唯一原因就是鼠标操作还在源源不断进入了Windows消息循环。WinForms中我能想到的一个相关方法就是Application.DoEvents()了。于是在g_frmInputInfo的窗体加载事件中,果然找到了好多Application.DoEvents()。但是随意删除这些,保不准会又出现那些问题。最后问AI,让我在加载前禁用DataGridView,加载完再复原,果然奏效了。
' 在这里去禁用DataGridViewcurrentDgv.Enabled = FalseIf blnInputInfo = False ThenblnInputInfo = Trueg_frmInputInfo = New frmInputInfog_frmInputInfo.MdiParent = g_frmMaing_frmInputInfo.Show()End IfShowChildform(g_frmInputInfo)currentDgv.Enabled = True'If (currentDgv.Name = "dgvDetail") Theng_frmInputInfo.clsAll()g_frmInputInfo.intMID = Me.dgvDetail.CurrentRow.Cells("MID").Valueg_frmInputInfo.txtID.Text = Me.dgvDetail.CurrentRow.Cells("制作单号").Valueg_frmInputInfo.readInfo()ElseIf currentDgv.Name = "dgvRedoDetail" Theng_frmInputInfo.clsAll()g_frmInputInfo.intMID = Me.dgvRedoDetail.CurrentRow.Cells("MID").Valueg_frmInputInfo.txtID.Text = Me.dgvRedoDetail.CurrentRow.Cells("制作单号").Valueg_frmInputInfo.readInfo()End If