I have 3 form ;
Form1 - Main Form
Form2 - Sub form ( contains progress bar and timer)
Form3 - Sub form with heavy contains which takes time for loading ( like parsing data from webpage and writing it to Datagridview at form load event)
I need to show form2 with a progress bar running while form3 is loading
I have following codes at Form1 ;
Me.Hide
Form2.Show()
Form3.Show()
codes from Form 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
The problem is progress bar starting but freezing at the beginning while Form3 is loading
Any idea for solution?
If you're new to programming then this may be a bit confusing but the answer is to push the code from the Load
event handler of Form3
into an Async
method and await it. Your UI freezes because you're doing work synchronously on the UI thread. You need to either use a secondary thread explicitly or use Async
/Await
. This:
Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Do some work.
End Sub
would become this:
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
Actually, that's probably more complex than necessary and this should work fine:
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
Having reread your question, what you probably need to do is have your async method be a function that retrieves and returns the data from the web page or whatever and then you load that data into your DataGridView
synchronously afterwards, e.g.
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
So the GetDataAsync
method returns a Task(Of DataTable)
, i.e. a Task
that asynchronously executes a function that returns a DataTable
. In the Load
event handler, you call that method and await the Task
, which means that your code will wait until the Task
has executed and returned its data but without blocking the UI thread as a synchronous call would do. The synchronous equivalent would be this:
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