Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB .NET > BackgroundWorker


Автор: noob4ever 19.7.2009, 23:19
вопрос: почему во время запуска фонового процесса форму не могу двигать и кнопки нажимать?? ведь запускается в отдельном процессе, кстати с копированием файла все выходит, а тут нет, форма не реагирует до завершения процесса.  я начинаю разбираться и постоянно натыкаюсь на какой нибудь камешек  

Код

 Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim i, j As Long
        For i = 0 To 1000000
            BackgroundWorker1.ReportProgress(j \ 10000)
            j += 1
        Next i  
  End Sub

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        BackgroundWorker1.RunWorkerAsync()
  End Sub



Автор: diadiavova 20.7.2009, 01:35
Дело в том, что из метода, который по идее должен вызываться асинхронно ты обращаешься к самому бэкграундвокеру, а он создан в том же потоке, что и форма, а стало быть и операция выполняется в нём же. Чтобы этого избежать надо обратиться к методу Invoke формы, для вызова метода в её потоке
Код

    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim repDel As New Report(AddressOf BackgroundWorker1.ReportProgress)
        For i As Integer = 0 To 1000000
            Me.Invoke(repDel, i \ 10000)
        Next i
    End Sub

    Delegate Sub Report(ByVal progress As Integer)

    Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
        BackgroundWorker1.RunWorkerAsync()
    End Sub


Вот так всё сработает

Автор: noob4ever 20.7.2009, 07:44
форма тормозит жутко, но управление не пропадает

кстате странное дело, время работы :

To 100000

Код

Me.Invoke(repDel, j \ 1000)   - 8с
BackgroundWorker1.ReportProgress(j \ 1000) - 2с

Автор: diadiavova 20.7.2009, 11:11
Ну так через посредника ведь всё делается, да ещё и в разных потоках, там есть свои сложности.
Можно попробовать реализовать по-другому. Не вызывать из другого потока метод ReportProgress, а вместо этого скидывать данные в переменную, а из основного потока считывать их по таймеру. Другой вариант не вызывать метод так часто, а только тогда, когда значение прогресса реально меняется
Код

            For i As Integer = 0 To 1000000
                If i Mod 10000 = 0 Then
                    Me.Invoke(repDel, i \ 10000)
                End If
            Next i

Автор: noob4ever 20.7.2009, 14:07
Цитата(diadiavova @ 20.7.2009,  11:11)
Ну так через посредника ведь всё делается, да ещё и в разных потоках, там есть свои сложности.
Можно попробовать реализовать по-другому. Не вызывать из другого потока метод ReportProgress, а вместо этого скидывать данные в переменную, а из основного потока считывать их по таймеру. Другой вариант не вызывать метод так часто, а только тогда, когда значение прогресса реально меняется
Код

            For i As Integer = 0 To 1000000
                If i Mod 10000 = 0 Then
                    Me.Invoke(repDel, i \ 10000)
                End If
            Next i

ясно, разобрался кажется. выходит прогресс из другова потока поэтому если часто отправлять ReportProgress, выходит так долго.

для проверки поставил 10 миллионов и за 1 секунду выполнилось если проверять остаток.  smile 

Автор: diadiavova 20.7.2009, 14:08
Не проверка, просто так ты вызываешь метод в 100 раз реже. На этом и экономишь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)