PROBLEMA COM TASK E THREAD
                    Olá, pessoal estou tento um problema que não sei mais como proceder.
Tenho um sistema que faço tratamento com banco de dados e planilha de excel, porém estou tentando utilizar as Task e/ou Thread para calcular e gravar dados na base de dados baseado na planilha.
Até ai o sistema está processando simultaneamente, mas o maior problema é o meu progressbar que eu preciso incrementar o value.
Ai eu faço o seguinte método em um programinha separado e esse funciona normalmente, perfeitamente
Mas agora no sistema que eu controlo o banco de dados o método invoke não funciona o sistema trava nessa linha e não faz mais nada.
No outro sistema eu faço da seguinte forma
Alguém tem alguma sugestão? Tentei diversas coisas e não tive resultado!
O problema é que se eu faço esse processo em um projeto a parte funciona, conforme primeiro código demonstrado.
Aguardo ansioso pela ajuda no fórum, já estou desesperado e no google não encontrei nada que me direcionasse para o caminho correto.
            Tenho um sistema que faço tratamento com banco de dados e planilha de excel, porém estou tentando utilizar as Task e/ou Thread para calcular e gravar dados na base de dados baseado na planilha.
Até ai o sistema está processando simultaneamente, mas o maior problema é o meu progressbar que eu preciso incrementar o value.
Ai eu faço o seguinte método em um programinha separado e esse funciona normalmente, perfeitamente
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim t1 As New Threading.Thread(AddressOf Count)
        t1.IsBackground = True
        t1.Start(100)
    End Sub
    Private Sub Count(ByVal Max As Object)
        If TypeOf Max Is Integer Then
            Count(CInt(Max))
        End If
    End Sub
[txt-color=#e80000]    Private Sub SetLabelText(ByVal text As Integer)
        If ProgressBar1.InvokeRequired Then
            ProgressBar1.Invoke(New Action(Of Integer)(AddressOf SetLabelText), text)
        Else
            ProgressBar1.Value = text
        End If
    End Sub[/txt-color]
    Private Sub Count(ByVal Max As Integer)
        For i = 1 To Max
            SetLabelText(i)
            Threading.Thread.Sleep(200)
        Next
    End SubMas agora no sistema que eu controlo o banco de dados o método invoke não funciona o sistema trava nessa linha e não faz mais nada.
No outro sistema eu faço da seguinte forma
    Private Sub ProcessarBanco(obj As IEnumerable(Of DataGridViewRow), sTipo As String, mascaraTGE As Integer, inativarGeral As Boolean)
        Dim oTGE As New clsSamTge()
        Select Case sTipo
            Case [Ô]N[Ô] [ô]Novos
                Dim lista = obj _
                    .Select(Function(s) New clsPrecosTuss With {
                        .Tuss_3_0 = s.Cells([Ô]Tuss_3_0[Ô]).Value,
                        .Tuss_2_0 = s.Cells([Ô]Tuss_2_0[Ô]).Value,
                        .Descricao = s.Cells([Ô]Descricao[Ô]).Value,
                        .Generico = s.Cells([Ô]Generico[Ô]).Value,
                        .Fracionamento = s.Cells([Ô]Fracionamento[Ô]).Value,
                        .Fabricante = s.Cells([Ô]Fabricante[Ô]).Value,
                        .Cnpj_fabricante = s.Cells([Ô]Cnpj_fabricante[Ô]).Value,
                        .Registro_anvisa = s.Cells([Ô]Registro_anvisa[Ô]).Value,
                        .Validade_anvisa = s.Cells([Ô]Validade_anvisa[Ô]).Value,
                        .Importar = s.Cells([Ô]Importar[Ô]).Value,
                        .Ativo = s.Cells([Ô]Ativo[Ô]).Value,
                        .Codigo_referencia = s.Cells([Ô]Codigo_referencia[Ô]).Value,
                        .Brasindice = s.Cells([Ô]Brasindice[Ô]).Value,
                        .Principio_ativo = s.Cells([Ô]Principio_ativo[Ô]).Value,
                        .Qtde_fracionada = s.Cells([Ô]Qtde_fracionada[Ô]).Value,
                        .Fim_vigencia = s.Cells([Ô]Fim_vigencia[Ô]).Value
                    })
                For Each row In lista
                    oTGE.InserirTGE(row, DataFechamento.Value, mascaraTGE, inativarGeral)
                    contagem += 1
                Next
            Case [Ô]E[Ô] [ô]Existentes
                Dim lista = obj _
                    .Select(Function(s) New clsPrecosTuss With {
                        .Tuss_3_0 = s.Cells([Ô]Tuss_3_0[Ô]).Value,
                        .Tuss_2_0 = s.Cells([Ô]Tuss_2_0[Ô]).Value,
                        .Descricao = s.Cells([Ô]Descricao[Ô]).Value,
                        .Generico = s.Cells([Ô]Generico[Ô]).Value,
                        .Fracionamento = s.Cells([Ô]Fracionamento[Ô]).Value,
                        .Fabricante = s.Cells([Ô]Fabricante[Ô]).Value,
                        .Cnpj_fabricante = s.Cells([Ô]Cnpj_fabricante[Ô]).Value,
                        .Registro_anvisa = s.Cells([Ô]Registro_anvisa[Ô]).Value,
                        .Validade_anvisa = s.Cells([Ô]Validade_anvisa[Ô]).Value,
                        .Importar = s.Cells([Ô]Importar[Ô]).Value,
                        .Ativo = s.Cells([Ô]Ativo[Ô]).Value,
                        .Codigo_referencia = s.Cells([Ô]Codigo_referencia[Ô]).Value,
                        .Brasindice = s.Cells([Ô]Brasindice[Ô]).Value,
                        .Principio_ativo = s.Cells([Ô]Principio_ativo[Ô]).Value,
                        .Qtde_fracionada = s.Cells([Ô]Qtde_fracionada[Ô]).Value,
                        .Fim_vigencia = s.Cells([Ô]Fim_vigencia[Ô]).Value
                    })
                For Each row In lista
                    oTGE.AtivarTGE(row.Tuss_3_0, row.Fim_vigencia, mascaraTGE)
                    contagem += 1
                Next
            Case [Ô]I[Ô] [ô]Inativos
                For Each row In obj
                    oTGE.AtivarTGE(row.Cells([Ô]tuss_3_0[Ô]).Value, row.Cells([Ô]fim_vigencia[Ô]).Value, mascaraTGE)
                    contagem += 1
                Next
            Case [Ô]IN[Ô] [ô]Inativar
                Dim c As Integer = Convert.ToInt32(Math.Ceiling(obj.Count() / 500))
                For xx = 0 To c - 1
                    Dim oInativar = obj.Skip(xx * 900).Take(900)
                    For Each row In oInativar
                        oTGE.InativarTGE(row.Cells([Ô]tuss_3_0[Ô]).Value, DataFechamento.Value.Date, mascaraTGE, inativarGeral)
                        contagem += 1
                    Next
                    GC.Collect()
                Next xx
        End Select
    End Sub
[txt-color=#e80000]    Private Sub UpdateProgres(ByVal _value As Integer)
            If pbProgresso.InvokeRequired Then
                pbProgresso.Invoke(New Action(Of Integer)(AddressOf UpdateProgres), _value) [ô]SISTEMA TRAVA AQUI E NÃO FAZ MAIS NADA NA THREAD
            Else
                pbProgresso.Value = _value
            End If
    End Sub[/txt-color]
    Private Sub btnProcessar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcessar.Click
        If MessageBox.Show([Ô]Data para Inativar Materiais/Medicamentos será [Ô] & DataFechamento.Value.ToString([Ô]dd/MM/yyyy[Ô]) & [Ô] confima a integração?[Ô], [Ô]Confirmar[Ô], MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) = DialogResult.Yes Then
            Dim lsTask As New List(Of Task)
            Dim tsk As Task
            Dim mascara As Integer = Integer.Parse(cboMascaraTGE.SelectedValue)
            Dim inativarGeral As Boolean = chkSomenteItensFimVigencia.Checked
            lblFraseAguarde.Text = [Ô]Aguarde... Processando as informações e gravando os dados.[Ô]
            Dim Existentes = dgvTuss.Rows.OfType(Of DataGridViewRow).Where(Function(w) w.Cells.Item([Ô]corLegenda[Ô]).Value = [Ô]E[Ô] And Not String.IsNullOrEmpty(w.Cells.Item([Ô]fim_vigencia[Ô]).Value))
            Dim Novos = dgvTuss.Rows.OfType(Of DataGridViewRow).Where(Function(w) w.Cells.Item([Ô]corLegenda[Ô]).Value = [Ô]N[Ô])
            Dim Inativos = dgvTuss.Rows.OfType(Of DataGridViewRow).Where(Function(w) w.Cells.Item([Ô]corLegenda[Ô]).Value = [Ô]I[Ô] And String.IsNullOrEmpty(w.Cells([Ô]fim_vigencia[Ô]).Value))
            Dim Inativar = dgvTuss.Rows.OfType(Of DataGridViewRow).Where(Function(w) w.Cells.Item([Ô]corLegenda[Ô]).Value = [Ô]IN[Ô])
            pbProgresso.Maximum = (Existentes.Count() + Novos.Count() + Inativos.Count() + Inativar.Count())
            pbProgresso.Value = 0
            contagem = 0
            pnlAguarde.Visible = True
            Application.DoEvents()
[txt-color=#e80000]            Dim trdProgress As New Threading.Thread(Sub()
                                                        While contagem <= pbProgresso.Maximum
                                                            UpdateProgres(contagem)
                                                            If (contagem Mod 1000) = 0 Then Application.DoEvents()
                                                            Threading.Thread.Sleep(50)
                                                        End While
                                                    End Sub)
            trdProgress.IsBackground = True
            trdProgress.Start()[/txt-color]
            [ô]tsk = New Task(Function() Processar([Ô]N[Ô], mascara,inativarGeral))
            [ô]tsk.Start()
            [ô]lsTask.Add(tsk)
            [ô]Threading.Thread.Sleep(3000)
            tsk = New Task(Sub() ProcessarBanco(Existentes, [Ô]E[Ô], mascara, inativarGeral))
            tsk.Start()
            lsTask.Add(tsk)
            Threading.Thread.Sleep(3000)
            [ô]tsk = New Task(Sub() ProcessarBanco(Inativos, [Ô]I[Ô], mascara, inativarGeral))
            [ô]tsk.Start()
            [ô]lsTask.Add(tsk)
            [ô]Threading.Thread.Sleep(3000)
            [ô]tsk = New Task(Function() Processar([Ô]IN[Ô], mascara,inativarGeral))
            [ô]tsk.Start()
            [ô]lsTask.Add(tsk)
            [ô]Threading.Thread.Sleep(3000)
            Task.WaitAll(lsTask.ToArray())
            If trdProgress.IsAlive Then trdProgress.Abort()
            MessageBox.Show([Ô]Processo Concluido[Ô])
            btnLimpar.Enabled = True
            pnlAguarde.Visible = False
        End If
    End SubAlguém tem alguma sugestão? Tentei diversas coisas e não tive resultado!
O problema é que se eu faço esse processo em um projeto a parte funciona, conforme primeiro código demonstrado.
Aguardo ansioso pela ajuda no fórum, já estou desesperado e no google não encontrei nada que me direcionasse para o caminho correto.
                    se tem uma coisa que é chata e comunicação form com Thread.
eu faço assim
Private Sub InserirEventos(eventos As String)
listEventos.Insert(0, eventos)
Me.Invoke(New MethodInvoker(Sub() lstEventos.Items.Insert(0, eventos)))
End Sub
            eu faço assim
Private Sub InserirEventos(eventos As String)
listEventos.Insert(0, eventos)
Me.Invoke(New MethodInvoker(Sub() lstEventos.Items.Insert(0, eventos)))
End Sub
                    exemplos...
https://www.codeproject.com/Articles/449594/Progress-Bars-Threads-Windows-Forms-and-You
            https://www.codeproject.com/Articles/449594/Progress-Bars-Threads-Windows-Forms-and-You
                    Então, mas é ai onde mora o problema! rsrsrs
O .Invoke não está funcionando o sistema cai nessa linha e trava não sai dali, mas também não apresenta erro.
            O .Invoke não está funcionando o sistema cai nessa linha e trava não sai dali, mas também não apresenta erro.
                    bom, eu estou fazendo no meu form
Me.Invoke(New MethodInvoker(Sub() lstEventos.Items.Insert(0, eventos)))
tenta no form em vez do progressbar.
                
            Me.Invoke(New MethodInvoker(Sub() lstEventos.Items.Insert(0, eventos)))
tenta no form em vez do progressbar.
                    Olhando o seu código me parece estar ocorrendo um Deadlock
Deadlock ocorre mais ou menos da seguinte forma, Thread 1 faz uma operação e então espera que Thread 2 termine algo antes dela continuar, e ao mesmo tempo Thread 2 faz algo que precisa esperar terminar na Thread 1, então ficam as duas travadas, uma esperando a outra.
No seu caso isso acontece da seguinte forma, você tem a Thread Principal, que é onde são criados os forms por padrão, e tem a Thread trdProgress. Pode ter outras threads por causa dos Tasks, mas o problema está mesmo nessas duas.
Então a Thread Principal é a que trata os eventos do seu Form, ela vai pegar o click do botão e disparar a outra trdProgress, até ai tudo bom, o problema deve ser no momento que você chama Task.WaitAll, neste ponto essa Thread vai ficar travada esperando as Tasks terminarem, mas ao mesmo tempo sua trdProgress vai chamar o Invoke no form, e a chamada do Invoke trava até ele terminar de executar, porém o Invoke faz com que o código seja executado na Thread Principal, que está travada e por isso ela não sai dali.
Mas eu diria que no seu caso esse é um péssimo uso de Threads, pois a operação é o que é chamado de [Ô]IO Bound[Ô], é uma operação que está ligada a espera de input ou output, como por exemplo a leitura ou gravação de um banco de dados, onde geralmente não se tem ganho real de performance por rodar em várias threads, e o pior ainda é que você criou uma thread só para atualizar o progress bar, o que nunca deveria ser feito já que a atualização da tela deve ser feita exclusivamente pela thread principal.
Eu diria que o ideal é você usar um background worker já que a única coisa que precisa é não travar a tela enquanto executa essa operação, e usar o report progress para atualizar o progresso.
            Deadlock ocorre mais ou menos da seguinte forma, Thread 1 faz uma operação e então espera que Thread 2 termine algo antes dela continuar, e ao mesmo tempo Thread 2 faz algo que precisa esperar terminar na Thread 1, então ficam as duas travadas, uma esperando a outra.
No seu caso isso acontece da seguinte forma, você tem a Thread Principal, que é onde são criados os forms por padrão, e tem a Thread trdProgress. Pode ter outras threads por causa dos Tasks, mas o problema está mesmo nessas duas.
Então a Thread Principal é a que trata os eventos do seu Form, ela vai pegar o click do botão e disparar a outra trdProgress, até ai tudo bom, o problema deve ser no momento que você chama Task.WaitAll, neste ponto essa Thread vai ficar travada esperando as Tasks terminarem, mas ao mesmo tempo sua trdProgress vai chamar o Invoke no form, e a chamada do Invoke trava até ele terminar de executar, porém o Invoke faz com que o código seja executado na Thread Principal, que está travada e por isso ela não sai dali.
Mas eu diria que no seu caso esse é um péssimo uso de Threads, pois a operação é o que é chamado de [Ô]IO Bound[Ô], é uma operação que está ligada a espera de input ou output, como por exemplo a leitura ou gravação de um banco de dados, onde geralmente não se tem ganho real de performance por rodar em várias threads, e o pior ainda é que você criou uma thread só para atualizar o progress bar, o que nunca deveria ser feito já que a atualização da tela deve ser feita exclusivamente pela thread principal.
Eu diria que o ideal é você usar um background worker já que a única coisa que precisa é não travar a tela enquanto executa essa operação, e usar o report progress para atualizar o progresso.
                    Quer algo descente, profissional mesmo? Use OOP e operações assÃncronas. Threads são para outra coisa...
                
            
                    Bom dia pessoal
Obrigado pelas respostas de todos, consegui fazer alguns ajustes no código que possibilitou chamar o Invoke no meu formulário.
Para que não fique algo vago vou explicar o que eu fiz.
Descobri que quando eu utilizo somente uma unica Thread e/ou Task o Invoke funciona normalmente, porém não consegui identificar um método que me possibilitasse a utilização de múltiplas Thread.
Ao realizar esse processo com múltiplas Thread o Invoke trava, pois está sendo chamada por processamentos diferentes. Ai resolvi deixar as Threads rodando e o progress incrementando pela Thread do formulário. Isso possibilitou o processamento da maneira que eu queria, mas não é a melhor solução.
KERPLUNK, escreveu:
KERPLUNK, você poderia me ajudar com essa situação de métodos async?
Esse sistema que solicitei ajuda é antigo e não dá pra mudar ele para 100% OOP, mas uma parte dele até tem OOP, mas não de uma forma legal.
Acontece que estou precisando iniciar um projeto do zero para centralizar todas as informações, ou seja, um repositório de dados que será consumido de sistemas WEB/DESKTOP/MOBILE. Então vem a pergunta, que tipo de estrutura fazer e como iniciar um projeto desse.
Podemos conversar no whatsapp ou skype? Me manda uma mensagem interna com o seu número ou skype.
Desde já agradeço.
            Obrigado pelas respostas de todos, consegui fazer alguns ajustes no código que possibilitou chamar o Invoke no meu formulário.
Para que não fique algo vago vou explicar o que eu fiz.
Descobri que quando eu utilizo somente uma unica Thread e/ou Task o Invoke funciona normalmente, porém não consegui identificar um método que me possibilitasse a utilização de múltiplas Thread.
Ao realizar esse processo com múltiplas Thread o Invoke trava, pois está sendo chamada por processamentos diferentes. Ai resolvi deixar as Threads rodando e o progress incrementando pela Thread do formulário. Isso possibilitou o processamento da maneira que eu queria, mas não é a melhor solução.
KERPLUNK, escreveu:
Citação:Quer algo descente, profissional mesmo? Use OOP e operações assÃncronas. Threads são para outra coisa...
KERPLUNK, você poderia me ajudar com essa situação de métodos async?
Esse sistema que solicitei ajuda é antigo e não dá pra mudar ele para 100% OOP, mas uma parte dele até tem OOP, mas não de uma forma legal.
Acontece que estou precisando iniciar um projeto do zero para centralizar todas as informações, ou seja, um repositório de dados que será consumido de sistemas WEB/DESKTOP/MOBILE. Então vem a pergunta, que tipo de estrutura fazer e como iniciar um projeto desse.
Podemos conversar no whatsapp ou skype? Me manda uma mensagem interna com o seu número ou skype.
Desde já agradeço.
                        Tópico encerrado , respostas não são mais permitidas