Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    [VB.NET] WPF - Utilizzo Dispatcher per aggiornamento UI blocca applicazione

    La mia applicazione si interfaccia ad una origine dati di tipo odbc, preleva i dati, li elabora e li inserisce in un controllo MindFusion.Calendar che li rappresenta sottoforma di appuntamenti.

    Il recupero dei dati viene eseguito attraverso un BackgroundWorker che funziona perfettamente.
    Il BGW gestisce l'evento WorkCompleted nel Thread UI di Wpf pertanto ha la possibilità di modificare le proprietà dei controlli come TextBox e altro ancora, compreso il calendario, in questa routine ho inserito l'avvio del Dispatcher ma sembra richiedere molto tempo lostesso,
    anche un minuto (circa 500 voci da inserire e no 500.000.000.000.000.000)

    L'inserimento delle voci nel calendario è una attività piuttosto pesante e richiede molto tempo,
    come posso gestire l'inserimento dei dati nel calendario in un thread separato?

    Ho provato con un Dispatcher nel seguente modo ma niente da fare

    codice:
    Dispatcher.BeginInvoke(DispatcherPriority.Normal, New AggiornaPrenotazioni_Delegate(AddressOf Me.SubAggiorna))
    Consigli??

  2. #2
    Ciao
    Dovresti far vedere anche il codice della procedura

    Facci sapere...
    Ciao

  3. #3
    routine che avvia l'aggiornamento

    codice:
     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
    
            Try
    
    
                'avvia il recupero dati
                'controlla che il BGW non sia impegnato in operazioni precedenti
                If ToODBC_BGWorker_Prenotazioni IsNot Nothing Then
                    If ToODBC_BGWorker_Prenotazioni.IsBusy = True Then Exit Sub
                End If
    
                'dichiaro un nuovo backgroundworker
                ToODBC_BGWorker_Prenotazioni = New BackgroundWorker
    
                'imposto gli handler dell'oggetto
                AddHandler ToODBC_BGWorker_Prenotazioni.DoWork, AddressOf ToODBC_BGWorker_Prenotazioni_DoWork
                AddHandler ToODBC_BGWorker_Prenotazioni.RunWorkerCompleted, AddressOf ToODBC_BGWorker_Prenotazioni_RunWorkerCompleted
                AddHandler ToODBC_BGWorker_Prenotazioni.ProgressChanged, AddressOf ToODBC_BGWorker_Prenotazioni_RunProgress
    
                'abilita l'avviso della fine del worker
                ToODBC_BGWorker_Prenotazioni.WorkerReportsProgress = True
                ToODBC_BGWorker_Prenotazioni.WorkerSupportsCancellation = True
    
                'avvia la procedura di verifica connettività
                ToODBC_BGWorker_Prenotazioni.RunWorkerAsync()
    
            Catch ex As Exception
    
                Errore(ex)
    
            End Try
    
        End Sub

    operazioni di recupero dei dati

    codice:
       ''' <summary>
        ''' recupera i dati sulle prenotazioni e li inserisce in una tabella
        ''' </summary>
        ''' <remarks></remarks>
        Sub ToODBC_BGWorker_Prenotazioni_DoWork()
    
            Try
    
                'istanzia una nuova tabella
                DataTableRisultati_Prenotazioni = New DataTable
    
                'se la connessione non è 'Nothing' e 'IsClosed'
                If Cn_Prenotazioni IsNot Nothing Then
                    'connessione in uno stato diverso
                    If Cn_Prenotazioni.State <> ConnectionState.Closed Then
                        'la richiude prima di riaprirla
                        Cn_Prenotazioni.Close()
                    End If
                End If
    
                'ricerca i dati di connessione
                Dim Dsn As String = RicercaImpostazioneInterna(4013)
                Dim Uid As String = RicercaImpostazioneInterna(4014)
                Dim Pwd As String = RicercaImpostazioneInterna(4015)
                Dim AnnoRicerca As String = RicercaImpostazioneInterna(4016)
    
                'controlla la validità delle impostazioni
                If Dsn.Length = 0 Then
                    'interrompe la routine
                    Exit Sub
                End If
    
                'controlla la validità delle impostazioni
                If Uid.Length = 0 Then
                    'interrompe la routine
                    Exit Sub
                End If
    
                'controlla la validità dell'anno di ricerca
                If AnnoRicerca.Length <> 4 Or IsNumeric(AnnoRicerca) = False Then
                    AnnoRicerca = Now.Year
                End If
    
                '--------------------------------------------------------------------
                'CONNESSIONE
                '--------------------------------------------------------------------
                'imposta la stringa di connessionecon i dati forniti dall'utente
                Dim ConnectionString As String = "DSN=" & Dsn & ";" & IIf(Uid.Length > 0, "UID=" & Uid & ";", "") & IIf(Pwd.Length > 0, "PWD=" & Pwd & ";", "")
    
                'istanzio una nuova connessione
                Cn_Prenotazioni = New OdbcConnection(ConnectionString)
    
                'imposta l'handler
                AddHandler Cn_Prenotazioni.StateChange, AddressOf Stato_Cn_Prenotazioni
    
    
    
                '--------------------------------------------------------------------
                'QUERY SQL: Recupera i dati delle prenotazioni dell'anno corrente
                '--------------------------------------------------------------------
                'SQLString = "SELECT * FROM PRENOT01 WHERE data_dal BETWEEN '" & AnnoRicerca.ToString.Substring(2, 2) & "/01/01" & "' AND '" & AnnoRicerca.ToString.Substring(2, 2) & "/12/31" & "' ORDER BY struttura"
    
                '--------------------------------------------------------------------
                'COMANDO
                '--------------------------------------------------------------------
                'imposta il command
                Dim Command = New OdbcCommand(ClausolaWhere, Cn_Prenotazioni)
    
    
                '--------------------------------------------------------------------
                'ADAPTER
                '--------------------------------------------------------------------
                'dichiara un nuovo adapter per popolare la tabella
                Dim AD As OdbcDataAdapter = New OdbcDataAdapter(ClausolaWhere, Cn_Prenotazioni)
    
    
                '--------------------------------------------------------------------
                'DATATABLE
                '--------------------------------------------------------------------
                'popola la tabella con i dati prelevati
                AD.Fill(DataTableRisultati_Prenotazioni)
    
                'carica il file di informazioni contatti da fonti esterne
                FileInformazioniOpzioniPrenotazioni = XDocument.Load(My.Settings.Percorso_RadicePadre.ToString & "\" & My.Settings.ApplicationName & "\" & "Informazioni" & "\" & "opzioniprenotazioni.xml")
    
                MsgBox("ricerca terminata con i seguenti risultati " & vbCrLf & DataTableRisultati_Prenotazioni.Rows.Count - 1)
    
            Catch ex As Exception
    
                Errore(ex)
    
            Finally
    
                'se la connessione non è 'Nothing' e 'IsClosed'
                If Cn_Prenotazioni IsNot Nothing Then
                    'connessione in uno stato diverso
                    If Cn_Prenotazioni.State <> ConnectionState.Closed Then
                        'la richiude prima di riaprirla
                        Cn_Prenotazioni.Close()
                    End If
                End If
    
            End Try
    
        End Sub
    'procedura nel thread principale che aggiorna l'interfaccia grafica


    codice:
        ''' <summary>
        ''' analisi sui dati ricevuti nella tabella nella cache memory
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Sub ToODBC_BGWorker_Prenotazioni_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
    
            Try
    
                If e.Cancelled = True Then
    
                    MsgBox("Cancellato")
    
                ElseIf e.Error IsNot Nothing Then
    
                    MsgBox("Errore: " & e.Error.Message)
    
                Else
    
                    'aggiorna il calendario
                    'Dispatcher.BeginInvoke(DispatcherPriority.Normal, New AggiornaPrenotazioni_Delegate(AddressOf Me.AggiornaCalendario))
    
                End If
    
            Catch ex As Exception
    
                Errore(ex)
    
            End Try
    
        End Sub

  4. #4
    Ciao Marco.
    Visto così il problema sembra essere nella sub AggiornaCalendario
    codice:
    'Dispatcher.BeginInvoke(DispatcherPriority.Normal, New AggiornaPrenotazioni_Delegate(AddressOf Me.AggiornaCalendario))
    Hai mostrato tutto il codice possibile ed immaginabile ... tranne quello che serviva e cioè .... quello che impegna il thread che gestisce la UI.

    Facci sapere...
    Ciao

  5. #5
    il codice è troppo lungo per essere inserito qui allora ho fatto una copia del file .vb lò compresso in un file .zip e inserisco il link qui sotto, clicca e si avvierà il download, poi cerca la routine AggiornaCalendario.

    Grazie in anticipo per l'aiuto, non sò più quale strada prendere.

    Scarica file vb

  6. #6
    Ciao Marco.
    il codice è troppo lungo per essere inserito qui
    Appunto .... ecco il problema.
    Nella routine invocata dal Dispatcher, deve esserci SOLO il codice per l'aggiornamento degli oggetti della UI .... solo il codice che, scritto in un thread separato, ti genererebbe un'eccezione di chrossthreading.
    Tutto il resto lo DEVI fare nel BackGroundWorker....

    Facci sapere...
    Ciao

  7. #7
    ma l'interfaccia grafica è aggiornata dinamicamente ovvero con dati creati in base ad una analisi di una tabella.

    Dovrei ciclare i dati della tabella nella routine ToODBC_BGWorker_Prenotazioni_RunWorkerCompleted e per ogni ciclo invocare il Dispatcher?

  8. #8
    Dovrei ciclare i dati della tabella nella routine ToODBC_BGWorker_Prenotazioni_RunWorkerCompleted e per ogni ciclo invocare il Dispatcher?
    No ... dovresti controllare i dati nella Routine DoWork ed aggiornare la UI solo quando serve.

    Facci sapere...
    Ciao

  9. #9
    Ho provato a seguire il tuo consiglio nel seguente modo

    1. Avvio BackGroundWorker nell'evento Click di Button1

    2. BackGroundWorker esegue tutte le operazioni di analisi dei dati vedi esempio:
    codice:
    sub Do_Work
    
    ..recupero dati su database
    
    'analisi dei dati non possibile con clausola where su query ma solo con più cicli
    ciclo next
    
      ciclo next
    
        if condizione then
    
                                          Dispatcher.BeginInvoke(DispatcherPriority.Normal, New AggiornaPrenotazioni_Delegate(AddressOf Me.AggiornaCalendario), app, TestoAggiuntivo, NomeStruttura)
    
    
        end if
    
      end next
    
    end next
    
    end sub
    ma viene sollevata un'eccezione
    codice:
    Il thread chiamante deve essere in modalità STA, perché questa è la modalità obbligatoria per molti componenti dell'interfaccia utente
    ma il BackGroundWorker non può essere impostato su STA ma solo su MTA

  10. #10
    Utente di HTML.it L'avatar di cassano
    Registrato dal
    Aug 2004
    Messaggi
    3,002
    Ma se non erro tale oggetto non ha un evento progress proprio per gestire queste cose ?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.