Прогрессбар зависает при загрузке другой формы - PullRequest
0 голосов
/ 18 октября 2018

У меня есть 3 формы;

Форма 1 - Основная форма

Форма 2 - Форма Sub (содержит индикатор выполнения и таймер)

Форма 3 - Форма Sub с тяжелым содержимым, которое занимаетвремя загрузки (например, анализ данных с веб-страницы и запись их в Datagridview при событии загрузки формы)

Мне нужно показать форму 2 с индикатором выполнения, работающим во время загрузки формы 3

У меня есть следующие коды в 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

Проблема в том, что индикатор запускается, но вначале зависает во время загрузки формы 3

Есть идеи для решения?

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Если вы новичок в программировании, это может немного сбить с толку, но ответ состоит в том, чтобы вставить код из обработчика событий Load Form3 в метод Async и дождаться его.Ваш пользовательский интерфейс зависает, потому что вы выполняете работу синхронно в потоке пользовательского интерфейса.Вам нужно либо явно использовать вторичный поток, либо использовать 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), то есть Task, который асинхронно выполняет функцию, которая возвращает DataTable.В обработчике события Load вы вызываете этот метод и ожидаете Task, что означает, что ваш код будет ждать, пока Task не выполнит и не вернет свои данные, но без блокировки потока пользовательского интерфейса, как в случае синхронного вызова.Синхронный эквивалент будет следующим:

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
0 голосов
/ 18 октября 2018

Попробуйте сделать процесс асинхронным, насколько я понимаю, тик таймера уже асинхронный, но в форме 1 вы могли бы использовать этот код внутри Задачи

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

Я никогда не заходил так далекона vb.net, так как я начал программировать на c #, но это должно сработать

...