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

    [VB2010] analisi function

    Se eseguo l' analisi del codice, relativamente a questa funzione, che ritorna il testo di un file:

    codice:
         Private Function LeggeLogFile() As String
            Dim LogFile As String
    
            Try
    
                Dim fs As FileStream = New FileStream(My.Settings.LogPath &  "\LogFile.txt", _
                   FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
                Dim sr As StreamReader = New StreamReader(fs)
                fs.Seek(0, SeekOrigin.Begin)
                LogFile = sr.ReadToEnd()
                sr.Close()
                fs.Close()
    
                Return LogFile
    
            Catch ex As Exception
    
                Return Nothing
    
            End Try
    
        End Function
    ottengo tre avvisi:

    Avviso 41 CA2000 : Microsoft.Reliability : Nel metodo 'frmMain.LeggeLogFile()' chiamare System.IDisposable.Dispose sull'oggetto 'fs' prima che tutti i relativi riferimenti siano esterni all'ambito.
    e questo:
    Avviso 43 CA2202 : Microsoft.Usage : L'oggetto 'fs' può essere eliminato più volte nel metodo 'frmMain.LeggeLogFile()'. Per evitare di generare System.ObjectDisposedException, è consigliabile chiamare Dispose su un oggetto non più di una volta
    e questo:
    Avviso 42 CA1822 : Microsoft.Performance : Il parametro 'this' (o 'Me' in Visual Basic) di 'frmMain.LeggeLogFile()' non è mai utilizzato. Contrassegnare il membro come static (o Shared in Visual Basic) o utilizzare 'this'/'Me' nel corpo del metodo o almeno una funzione di accesso delle proprietà, se appropriato.
    Per cercare di rimediare al primo avviso ho pensato di modificare il codice così:

    codice:
         Private Function LeggeLogFile() As String
            Dim LogFile As String
            Dim fs As FileStream 
    
            Try
    
                fs = New FileStream(My.Settings.LogPath & "\LogFile.txt", FileMode.Open, _
                   FileAccess.Read, FileShare.ReadWrite)
                Dim sr As StreamReader = New StreamReader(fs)
                fs.Seek(0, SeekOrigin.Begin)
                LogFile = sr.ReadToEnd()
                sr.Close()
    
                Return LogFile
    
            Catch ex As Exception
    
                Return Nothing
    
            Finally
    
                fs.Close()
    
            End Try
    
        End Function
    ma ottengo un ulteriore avviso che mi dice che la variabile fs (in Finally) viene utilizzata prima che le sia stato assegnato un valore.

    Riguardo al secondo avviso proprio non vedo dove fs possa essere chiusa più volte.

    Il terzo è letteralmente arabo...

    Ty for any info

  2. #2
    Utente di HTML.it
    Registrato dal
    May 2011
    Messaggi
    119
    Prova con un blocco di using (pressapoco questo)
    codice:
    Using fs As FileStream = New FileStream(My.Settings.LogPath &  "\LogFile.txt", _                  FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
      Try
                Dim sr As StreamReader = New StreamReader(fs)
                fs.Seek(0, SeekOrigin.Begin)
                LogFile = sr.ReadToEnd()
    
     Catch ex As Exception
         System.Diagnostics.Debug.WriteLine(ex.Message)
          System.Diagnostics.Debug.WriteLine(ex.StackTrace)
    			RetValue = False
      Finally
    	fs.Close()
    				
      End Try
    End Using

  3. #3
    No, è esattamente il contrario: l' errrore è MOLTO più probabile che avvenga su fs... con Using non lo puoi gestire.

    Dopo millanta ricerche sul web, sono arrivato alla soluzione:

    codice:
      Private Shared Function LeggeLogFile() As String
            Dim LogFile As String
    
            Dim fs As FileStream = Nothing
    
            Try
    
                fs = New FileStream(My.Settings.LogPath & "\PokerStars.log.0", FileMode.Open, _
                                       FileAccess.Read, FileShare.ReadWrite)
               
                 Using sr As StreamReader = New StreamReader(fs)
    
                    fs.Seek(0, SeekOrigin.Begin)
                    LogFile = sr.ReadToEnd()
    
                    fs = Nothing
    
                End Using
    
                Return LogFile
    
            Catch ex As Exception
    
                Return Nothing
    
            Finally
    
                If fs IsNot Nothing Then fs.Dispose()
    
            End Try
    
        End Function
    Così il primo avviso è sparito. Dichiarando Shared la Function è sparito anche il terzo. Rimane il secondo avviso, ma è evidente che è un errore dell' analisi, visto che il secondo fs.Dispose() è condizionale

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da eziogsv
    No, è esattamente il contrario: l' errrore è MOLTO più probabile che avvenga su fs... con Using non lo puoi gestire.
    L'uso di using non ha nulla a che vedere con la gestione degli errori, che è possibile attuare sia in presenza che in assenza di using.

    Il fatto è che using andrebbe utilizzato per tutte le classi che implementano IDisposable, mentre tu l'hai utilizzato solo per una di queste (lo StreamReader) senza estenderlo anche a FileStream.

    I warning che ti vengono restituiti sono abbastanza semplici da individuare.

    Se usi il costrutto Try...Finally, dove il codice nel blocco Finally "finalizza" un oggetto, la sua creazione (con l'uso di New) deve essere fatta ovviamente all'esterno del blocco, altrimenti - qualora il costruttore non vada a buon fine - finisci per agire su una variabile che contiene un riferimento nullo.

    La struttura corretta (seguendo il tuo esempio a grandi linee), quindi, è questa:

    codice:
    fs = New FileStream(My.Settings.LogPath & "\PokerStars.log.0", FileMode.Open, _
      FileAccess.Read, FileShare.ReadWrite)
    
    Try
    
        ' ...
    
    Finally
    
        fs.Dispose()
    
    End Try
    Con l'adozione di Using il codice si semplifica ulteriormente:


    codice:
    Using fs As New FileStream(My.Settings.LogPath & "\PokerStars.log.0", FileMode.Open, _
      FileAccess.Read, FileShare.ReadWrite)
    
        ' ...
    End Using

    Tutte le impostazioni a Nothing che hai fatto nel codice, così come i relativi If...Then che hai inserito per controllare questo valore, sono inutili e possono essere rimossi.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Ecco il codice che hai scritto tu, ulteriormente semplificato, che non dovrebbe generarti alcun warning tra quelli che hai indicato:


    codice:
    Private Shared Function LeggeLogFile() As String
    
        Try
            Using fs As FileStream = New FileStream(My.Settings.LogPath & "\PokerStars.log.0", FileMode.Open, _
                    FileAccess.Read, FileShare.ReadWrite)
                Using sr As StreamReader = New StreamReader(fs)
                    Return sr.ReadToEnd()
                End Using
            End Using
        Catch ex As Exception
            Return Nothing
        End Try
    
    End Function
    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  6. #6
    Funge perfettamente, ty.

    E pensare che l' esempio di annidare Try / Finally e Using lo ho trovato su Msdn proprio in un esempio con Filestream e Streamreader. Mavaff.....

  7. #7
    *** NEGATIVO ***

    La routine funge perfettamente (come d' altronde la mia), ma crea ugualmente avviso.

    Fai questa velocissima prova: nuovo progetto ==> Windows Form, inserisci questo codice:

    codice:
    Imports System.IO
    
    Public Class Form1
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    
            Dim File As String = LeggeLogFile()
    
        End Sub
    
        Private Shared Function LeggeLogFile() As String
    
            Try
                Using fs As FileStream = New FileStream("MFile", FileMode.Open, _
                        FileAccess.Read, FileShare.ReadWrite)
                    Using sr As StreamReader = New StreamReader(fs)
                        Return sr.ReadToEnd()
                    End Using
                End Using
            Catch ex As Exception
                Return Nothing
            End Try
    
        End Function
    
    End Class
    Se lanci l' analisi ottieni questo avviso:

    codice:
    Avviso1 CA2202 : Microsoft.Usage : L'oggetto 'fs' può essere eliminato più volte nel
    metodo 'Form1.LeggeLogFile()'. Per evitare di generare System.ObjectDisposedException, è
    consigliabile chiamare Dispose su un oggetto non più di una volta.: Lines: 19
    Ove la linea 19 è il secondo End Using

    Mi sa tanto che l' esempio di MSDN, con l' eliminazione condizionale di fs, sia quello giusto...


    EDIT

    Eliminando il secondo Using:

    codice:
                Using fs As FileStream = New FileStream("MFile", FileMode.Open, _
                        FileAccess.Read, FileShare.ReadWrite)
                    Dim sr As StreamReader = New StreamReader(fs)
                        Return sr.ReadToEnd()
                End Using
    è sparito l' avviso.... può essere che sr venga portato automaticamente a nothing portando a nothing fs all' uscita del blocco Using????

    Dovrebbe essere così... l' alternativa è che l' analisi di VS2010 sia sballata.
    .
    .

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    L'analisi fatta da Microsoft è generica e riferita a tutte le classi, quindi non tiene conto dei casi particolari dove l'errore a cui si riferisce in realtà non si verifica perché la classe è in grado di gestirlo.

    Temo ti venga segnalato perché lo StreamReader si appoggia al FileStream e tenta di fare la Dispose di questo quando viene "distrutto"; l'uso di Using anche sul FileStream, quindi, potrebbe causare una seconda chiamata a Dispose, eventualità che, comunque, non genera alcun errore per queste classi.

    Per semplificare ed evitare il warning, potresti evitare l'uso di Using nella creazione dell'istanza di FileStream.

    Come opinione personale, penso che l'analisi di Microsoft sia comunque molto spesso eccessivamente rigida: mi è capitato di usarla una volta e riusciva a darmi un warning suggerendomi una correzione, poi una volta corretto ripeteva un'altra segnalazione indicandomi di rimetterlo come prima. In breve, è un'analisi che va "presa con le molle", come si suol dire.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  9. #9
    Originariamente inviato da alka Per semplificare ed evitare il warning, potresti evitare l'uso di Using nella creazione dell'istanza di FileStream.
    Ehm... che poi sarebbe esattamente l' esempio che ho riportato io...... o no?

    Ho comunque bisogno di un Try per gestire un eventuale errore su fs, e quindi di un finally per eliminare fs in caso di errore... esattamente l' esempio riprtato su Msdn.

    Però con l' ultimo codice da me riportato non ho un avviso che mi dice che sr deve essere eliminato : a questo punto non si può ritenere che venga senz' altro portato a nothing insieme a fs con un unico using???

  10. #10
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da eziogsv
    Ehm... che poi sarebbe esattamente l' esempio che ho riportato io...... o no?
    Il problema sta nel legame tra le due classi, FileStream e StreamReader, in cui la seconda si aggancia alla prima e la "finalizza" quando non serve più.

    In ogni caso, il costrutto Using è una scorciatoia per il Try...Finally con una chiamata a Dispose, quindi se l'analisi ti restituisce un risultato differente credo che tu possa sostanzialmente ignorarla.

    Originariamente inviato da eziogsv
    Ho comunque bisogno di un Try per gestire un eventuale errore su fs, e quindi di un finally per eliminare fs in caso di errore... esattamente l' esempio riprtato su Msdn.
    Sì, questo è corretto.

    Originariamente inviato da eziogsv
    Però con l' ultimo codice da me riportato non ho un avviso che mi dice che sr deve essere eliminato : a questo punto non si può ritenere che venga senz' altro portato a nothing insieme a fs con un unico using???
    Nulla viene portato a Nothing, con o senza Using, a meno di non farlo manualmente; semplicemente, le variabili vanno "out of scope" e quindi non sono più accessibili; questo fa sì che il garbage collector rilasci anche gli oggetti associati.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

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.