进度条冻结,而另一个表单加载



我有 3 种形式;

表单 1 - 主表单

Form2 - 子窗体(包含进度条和计时器(

Form3 - 包含大量内容的子表单,加载需要时间(例如从网页解析数据并在表单加载事件时将其写入 Datagridview(

我需要在加载 form3 时显示带有运行进度条的 form2

我在 Form1 有以下代码;

Me.Hide
Form2.Show()
Form3.Show()

表格 2 中的代码;

Public Class Form2
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadingTimer.Enabled = True
End Sub
Private Sub LoadingTimer_Tick(sender As Object, e As EventArgs) Handles LoadingTimer.Tick
If MyProgressBar.Value <= MyProgressBar.Maximum - 1 Then
MyProgressBar.Value += 10
End If
If MyProgressBar.Value = 100 Then
LoadingTimer.Enabled = False
Me.Close()
End If
If Label1.ForeColor = Color.LimeGreen Then
Label1.ForeColor = Color.White
Else
Label1.ForeColor = Color.LimeGreen
End If
End Sub
End Class

问题是进度条开始但在加载 Form3 时开始时冻结

有什么解决方案的想法吗?

如果你是编程新手,那么这可能有点令人困惑,但答案是将代码从Form3Load事件处理程序推送到Async方法中并等待它。 你的 UI 冻结,因为你正在 UI 线程上同步执行工作。 您需要显式使用辅助线程或使用Async/Await。 这:

Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Do some work.
End Sub

会变成这样:

Private Async Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Await DoWork()
End Sub
Private Async Function DoWork() As Task
Await Task.Run(Sub()
'Do some work.
End Sub).ConfigureAwait(False)
End Function

实际上,这可能比必要的更复杂,这应该可以正常工作:

Private Async Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Await Task.Run(Sub()
'Do some work.
End Sub).ConfigureAwait(False)
End Sub

重新阅读您的问题后,您可能需要做的是让您的异步方法成为一个函数,该函数从网页或其他内容检索并返回数据,然后您随后将该数据同步加载到您的DataGridView中,例如

Private Async Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.DataSource = Await GetDataAsync()
End Sub
Private Async Function GetDataAsync() As Task(Of DataTable)
Return Await Task.Run(Function()
Dim table As New DataTable
'Populate table here.
Return table
End Function).ConfigureAwait(False)
End Function

所以GetDataAsync方法返回一个Task(Of DataTable),即异步执行返回DataTable的函数的Task。 在Load事件处理程序中,调用该方法并等待Task,这意味着您的代码将等到Task执行并返回其数据,但不会像同步调用那样阻塞 UI 线程。 同步等效项是这样的:

Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.DataSource = GetData()
End Sub
Private Function GetData() As DataTable
Dim table As New DataTable
'Populate table here.
Return table
End Function

尝试使过程异步,据我了解,计时器时钟周期已经是异步的,但在 form1 中,您可以使用 可以在任务中拥有该代码

Me.Hide
Task.Run(Function() Form2.Show())
Form3.Show()

自从我开始在 c# 上编程以来,我从未在 vb.net 上达到这一步,但这应该可以解决问题

最新更新