Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

CreativeJopa

Usando Backgroundworker

Mensagens Recomendadas

CreativeJopa

Boas.

Estou a dar os primeiros passos com a utilização do backgroundworker e não estou a conseguir fazer o pretendido.

Private Sub backgroundworker_itens_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles backgroundworker_itens.DoWork
        ligacao_database.ConnectionString = ("Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\database.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True")
        ligacao_database.Open()
        intrucao_database = New SqlCommand("SELECT count(id) as [nr_registos] FROM table_registos", ligacao_database)
        leitura_database = intrucao_database.ExecuteReader
        If leitura_database.Read Then
            TextBlock_nr_albuns.Text = ("(" & leitura_database("nr_registos)")
        End If
                leitura_database.Close()
        ligacao_database.Close()
    End Sub

Neste caso, pretendo que a aplicação vá à base de dados e me devolva um valor (nr de linhas). O código funciona no loaded da página, mas usando o backgroundworker, surge o erro "The calling thread cannot access this object because a different thread owns it.", na linha "TextBlock_nr_albuns.Text = ("(" & leitura_database("nr_registos)")".

Aluem me explica como o conseguir?

cumprimentos.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
ribeiro55

O backgroundworker está a operar num thread diferente do thread do user interface.

Não podes simplesmente afectar valores num thread a partir de outro.

Faz uma pesquisa com as chaves delegate e invoke.

Caso não tenhas sorte, volta cá :)


Sérgio Ribeiro


"Great coders aren't born. They're compiled and released"
"Expert coders do not need a keyboard. They just throw magnets at the RAM chips"

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
CreativeJopa

Caça, agradeço a ajuda, mas tal como o website que mostrei, não consigo aplicar o código na aplicação. Usando o seu exemplo (e o do woutro website), diz que "Invoke" não é membro da Lisbox1.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
bioshock

Caça, agradeço a ajuda, mas tal como o website que mostrei, não consigo aplicar o código na aplicação. Usando o seu exemplo (e o do woutro website), diz que "Invoke" não é membro da Lisbox1.

Diz que não é membro porque em vez de Lisbox1, será Listbox1.

Contudo, pelo que vi, tu queres "atirar" o que vem da base de dados para dentro de uma Textbox. Deixo-te um exemplo completo:

    Private WithEvents bgw As New BackgroundWorker
    Private Delegate Sub Text_Delegate(ByVal text As TextBox)
    Private Sub SetText_ThreadSafe(ByVal text As TextBox)
        If text.InvokeRequired Then
            Dim myDelegate As New Text_Delegate(AddressOf SetText_ThreadSafe)
            text.Invoke(myDelegate, New Object() {text})
        Else
            Dim connection As New SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\database.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True")
            connection.Open()
            Dim command As New SqlCommand("SELECT COUNT(ID) FROM Tabela", connection)
            Dim mr_Reader As SqlDataReader = command.ExecuteReader
            While mr_Reader.Read
                text.Text = mr_Reader(0)
            End While
        End If
    End Sub
    Private Sub bgw_Work() Handles bgw.DoWork
        SetText_ThreadSafe(TextBox1)
    End Sub
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        bgw.RunWorkerAsync()
    End Sub

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
CreativeJopa

Agradeço a ajuda. Consegui fazer o pretendido.

No entanto, agora tenho outro objectivo (usando o backgroundworker na mesma), que é criar X vezes um usercontrol, mas surge-me um erro: "The calling thread must be STA, because many UI components require this.".

Já fiz uma pesquisa e não entendi o que tenho que alterar.

Private Sub backgroundworker_itens_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles backgroundworker_itens.DoWork
For i = 1 To 20
Dim new_UserControl_actividade_recente As New UserControl_actividade_recente
AddHandler new_UserControl_actividade_recente.handler_UserControl_actividade_recente_MouseLeftButtonDown, AddressOf handler_UserControl_actividade_recente
WrapPanel_miniaturas.Children.Add(new_UserControl_actividade_recente)
Next
End Sub

Analisei este artigo, mas aparentemente não consigo por a funcionar em background, pois a aplicação bloqueia até executar o código.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
CreativeJopa

Trago uma actualização do problema:

Imports System.Data.SqlClient
Imports System.Threading

Class Page_adicoes_recentes
    Dim ligacao_database As New SqlConnection
    Dim intrucao_database As SqlCommand
    Dim leitura_database As SqlDataReader


    Dim calculo_adicoes_recentes As New delegate_calculo_adicoes_recentes(AddressOf adress_calculo_adicoes_recentes)
    Private Delegate Sub delegate_calculo_adicoes_recentes(ByVal valor As UserControl)
    Private Sub adress_calculo_adicoes_recentes(ByVal valor As UserControl)
        WrapPanel_miniaturas.Children.Add(valor)
    End Sub

    Public Sub Thread_calculo_adicoes_recentes()
        For i = 1 To 10
            Thread.Sleep(1000)
            Dim new_UserControl_adicoes_recentes_miniaturas As New UserControl_adicoes_recentes_miniaturas
            Dispatcher.Invoke(calculo_adicoes_recentes, new_UserControl_adicoes_recentes_miniaturas)
        Next
    End Sub
    Private Sub Page_adicoes_recentes_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        ligacao_database.ConnectionString = ("Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\database.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True")
        ligacao_database.Open()
        Dim Thread_adicoes_recentes As New System.Threading.Thread(AddressOf Thread_calculo_adicoes_recentes)
        Thread_adicoes_recentes.SetApartmentState(ApartmentState.STA)
        Thread_adicoes_recentes.Start()

    End Sub

    Private Sub Page_adicoes_recentes_Unloaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
        ligacao_database.Close()
    End Sub

End Class

O objectivo é adicionar 10x o "UserControl_adicoes_recentes_miniaturas", mas obtenho o erro "The calling thread cannot access this object because a different thread owns it." na linha "WrapPanel_miniaturas.Children.Add(valor)".

Alguém me pode ajudar?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.