How to wait for a Thread to finish and how to receive values from it?

Asked

Viewed 2,006 times

2

I am working on a situation that requires the use of multiprocessing.

I need to read files and a shitload of lawsuits that could take some time. During this process, I want to display a kind of user window (Aguarde...) without compromising the UI thread and without causing the whitish ones that occur when the graphical interface is no longer updated.

However, it is difficult to know when the thread has finished its work, because the process has no set time and can vary according to the volume of information handled and the configuration of the machine. Searching the internet, I found the Join method, responsible for waiting for the end of the threads processing. However I am obliged to stipulate a time for him to leave the waiting mode and as I mentioned before, the process can take from little to long.

My thread performs a method that has feedback and I am also unable to retrieve the information from this method. I searched on the internet, but it is not clear yet. I do not know how to recover the data processed by thread.

My thread executes a method that captures database information, compares it to a text file, and then returns a ArrayList with the discrepant data. The problem is to know when the process has ended and receive the result of this method.

Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles Button2.Click
    Dim OPF As New OpenFileDialog
    Dim Caminho As String
    Dim Aviso As New frmWarning
    Dim ListaEntradas As ArrayList

    If IO.Directory.Exists(Path) Then
        Caminho = Path
    Else
        Caminho = Path.Substring(1, 3)
    End If

    With OPF
        .InitialDirectory = Caminho
        .ShowDialog()
    End With

    Aviso.Show()
    Dim compara As New Thread(AddressOf TDNFEntradas)
    compara.Start(OPF.FileName)

    'ListaEntradas = (E AGORA? COMO RECEBER A LISTA DA THREAD?)
    Aviso.Close()


End Sub

Private Function TDNFEntradas(ByVal Endereco As String) As ArrayList
    Dim NFentradas As New ArrayList
    Dim Mensagem As New frmWarning
    Dim Lista As New ArrayList

    HabilitarControlesNF(False) ' Desabilita controles do formulario
    NFentradas = CapturarNotas(Endereco, 0) ' Carrega Numeros das Notas dentro de um arrayList
    Lista = CompNotasEntrada(NFentradas) ' Compara dados da lista com o banco e retorna as diferenças numa outra lista
    HabilitarControlesNF(True) 'Habilita controles do formulario

    Return Lista 'Retorna lista com discrepancias

End Function

1 answer

1


To get the return of a Function executed in Thread, you need to use a BackgroundWorker:

Private WithEvents BackgroundWorker1 As New System.ComponentModel.BackgroundWorker

Your final code will look something like this:

Private Class Entradas
    Public CaminhoArquivo As String
    Function TDNFEntradas() As ArrayList
        Dim NFentradas As New ArrayList
        Dim Mensagem As New frmWarning
        Dim Lista As New ArrayList

        HabilitarControlesNF(False) ' Desabilita controles do formulario
        NFentradas = CapturarNotas(CaminhoArquivo, 0) ' Carrega Numeros das Notas dentro de um arrayList
        Lista = CompNotasEntrada(NFentradas) ' Compara dados da lista com o banco e retorna as diferenças numa outra lista
        HabilitarControlesNF(True) 'Habilita controles do formulario

        Return Lista 'Retorna lista com discrepancias

    End Function
End Class

Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles Button2.Click
    Dim OPF As New OpenFileDialog
    Dim Caminho As String
    Dim Aviso As New frmWarning
    Dim ListaEntradas As ArrayList
    Dim ClasseEntradas As New Entradas

    If IO.Directory.Exists(Path) Then
        Caminho = Path
    Else
        Caminho = Path.Substring(1, 3)
    End If

    With OPF
        .InitialDirectory = Caminho
        .ShowDialog()
    End With

    Entradas.CaminhoArquivo = OPF.FileName
    Aviso.Show()

    ' Executar Thread com Worker
    BackgroundWorker1.RunWorkerAsync(Entradas)
End Sub 

' Este é o método que realiza o trabalho em Thread.
Private Sub BackgroundWorker1_DoWork(
    ByVal sender As Object, 
    ByVal e As System.ComponentModel.DoWorkEventArgs
    ) Handles BackgroundWorker1.DoWork

    Dim Entradas As ClasseEntradas = CType(e.Argument, Entradas)
    ' Retorne o valor por e.Result
    e.Result = Entradas.TDNFEntradas()
End Sub 

' Este método executa quando a Thread termina
Private Sub BackgroundWorker1_RunWorkerCompleted(
    ByVal sender As Object,
    ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs
    ) Handles BackgroundWorker1.RunWorkerCompleted

    ' Obter Resultado
    Dim Lista As ArrayList = CDbl(e.Result)
    ' Trate aqui sua lista
End Sub

Basically I adapted this article here: http://msdn.microsoft.com/en-us/library/wkays279.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-4

  • I arrived at the same article, however... the problem is the outcome conversation at the end... I find no way to convert it to list.

  • Ali in the method BackgroundWorker1_RunWorkerCompleted. Value not converted back? What is missing?

  • It is converted to Double, right? The.o' and my list is a string arraylist...

  • Why? e.Result is Object, nay Double: http://msdn.microsoft.com/pt-br/library/system.componentmodel.doworkeventargs.result(v=vs.110). aspx

  • Cdbl(e. Result) <-- understood? in that part rolls a conversation for double, however I need to convert it to some kind of table structure or a collection(Arraylist).

  • Hmm... no need to chat, I managed to play on the direct list. Grateful!

  • @Would you please mark the answer as accepted, for the benefit of the community? Thank you!

  • 1

    Sorry, I had forgotten :D very grateful

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.