VB.NET中Form.Shown先于控件加载,求类似JS window.onload的实现
解决方法
你的问题根源在于Shown事件中同步执行了耗时的循环操作,导致UI线程被阻塞,窗体来不及完成图片和标签的绘制就开始处理循环。要实现类似JavaScript中window.onload的效果,让窗体完全渲染后再启动进度条操作,可以通过以下方式处理:
方法1:使用BeginInvoke延迟执行加载逻辑
通过BeginInvoke将加载代码放到UI线程的消息队列末尾,确保窗体先完成所有绘制操作后再执行循环:
Private Sub FRM_CargaInicial_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown LBL_Carga.Visible = True ' 将加载逻辑放入BeginInvoke,等待UI完成渲染 Me.BeginInvoke(Sub() Dim Dt As DataTable = New DataTable If conexion.EjecutarSQL("EXEC [GIM_RECURSOS].[IMAGEN].[SP_IMPORTAR]", Dt) Then PRB_Carga.Maximum = Dt.Rows.Count PRB_Carga.Value = 0 For Each fila As DataRow In Dt.Rows Iconos.Add(New OBJIcono(fila.Item("ID_INFORMACION"), fila.Item("CLAVE"), fila.Item("VALOR"))) PRB_Carga.Value += 1 ' 强制刷新进度条,确保实时显示进度 PRB_Carga.Refresh() Next fila End If Me.Hide() FRM_Ingreso.Show() End Sub) End Sub
关键说明
BeginInvoke会把传入的委托方法加入UI线程的消息队列,等当前所有待处理的UI消息(比如绘制窗体控件)执行完毕后才会运行,这样就能保证窗体的图片和标签先显示出来。- 在循环中调用
PRB_Carga.Refresh()可以强制进度条立即重绘,避免因为UI线程繁忙导致进度条一次性填满的问题。
进阶优化(可选)
如果SQL查询或循环操作耗时较长,建议使用后台线程(如Task.Run)来处理,避免阻塞UI线程,同时通过Invoke更新UI控件:
Private Async Sub FRM_CargaInicial_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown LBL_Carga.Visible = True ' 等待UI完成渲染 Await Task.Delay(10) Dim Dt As DataTable = Await Task.Run(Function() Dim table As New DataTable conexion.EjecutarSQL("EXEC [GIM_RECURSOS].[IMAGEN].[SP_IMPORTAR]", table) Return table End Function) If Dt IsNot Nothing AndAlso Dt.Rows.Count > 0 Then PRB_Carga.Maximum = Dt.Rows.Count PRB_Carga.Value = 0 For Each fila As DataRow In Dt.Rows Iconos.Add(New OBJIcono(fila.Item("ID_INFORMACION"), fila.Item("CLAVE"), fila.Item("VALOR"))) ' 在UI线程更新进度条 Me.Invoke(Sub() PRB_Carga.Value += 1) Next fila End If Me.Hide() FRM_Ingreso.Show() End Sub
这个版本使用Async/Await和Task.Run将耗时的SQL查询放到后台线程,UI线程不会被阻塞,窗体渲染和进度条更新会更流畅。
内容的提问来源于stack exchange,提问作者Gus
相关产品推荐
相关产品推荐

