Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

di il
12 risposte

Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

Come da oggetto vi posto parte del seguente codice
StringBuilder theBufToFile = new StringBuilder("");
...
for
{
...
theBufToFile.Append(array[i] + "-");
}
...
File.WriteAllText(fullPath, theBufToFile.ToString());
La documentazione recita: (link)
Crea un nuovo file, ne scrive il contenuto e quindi lo chiude

Ne consegue che se lo chiude, allora all'atto della creazione, e anche nella scrittura il file è lockato a tutti gli altri programmi/servizi, fino a che non ha finito di scriverci, che chiude la connessione.

Giusto o Sbaglio ?

Grazie.

12 Risposte

  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Giusto
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Giusto, anche se non ho capito perché hai aggiunto il for che riempie theBufToFile.
    Mentre il ciclo for riempie theBufToFile, il file non è lockato ed è liberamente modificabile da altri processi.
    Il file è lockato solo quando si arriva all'istruzione: File.WriteAllText(fullPath, theBufToFile.ToString());
    L'istruzione File.WriteAllText(); salva il file in un colpo solo, su HDD datato 10MB di testo vengono salvati 0.1secondi.
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Ciao, perché il buffer viene riempito da diversi array come in codice. A completamento ultimato, scrive.
                StringBuilder theBufToFile = new StringBuilder(""); //Creo un buffer vuoto
                for (int i = 1; i <= ValForFile.Count; i++) //Preparo il buffer con le variabili
                {
                    theBufToFile.Append(ValForFile[i] + "-");
                }
                if (Save_aData(ref theBufToFile) == false) //Salvo il file. Se non ci siamo riusciti, riprovo un'altra sola volta
                {
                    Thread.Sleep(100); //Sospendo per 100 millisecondi (dovrebbe essere sufficiente)
                    bolTrash = Save_aData(ref theBufToFile); //Salvo e dimentico l'esito del salvataggio
                }
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    " Thread.Sleep(100); //Sospendo per 100 millisecondi (dovrebbe essere sufficiente)"
    è necessario?
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Per sapere se è sufficiente, dovrei sapere quanti mega devi salvare, quanti altri processi accedono allo stesso file e con quale velocità.
    Se hai nel form dei controlli che monitorizzano lo stato del programma potresti far diventare rossa una label che avverte che il file non è stato salvato...
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Thread.Sleep(100); //Sospendo per 100 millisecondi (dovrebbe essere sufficiente)
    In realtà non è una domanda rivolta a voi: è un commento che ho nel mio codice
    Cmq, visto che vi siete prodigati a rispondermi ad una domanda che non era una domanda (w il rigiro di parole), è anche corretto nei vostri confronti che vi risponda:

    - intanto è un servizio per cui niente interfaccia grafica.
    - aspettare 100 ms va bene per le mie esigenze: questo file viene letto da un'altra applicazione (sempre fatta da me) ed entrambi ci accedono ogni secondo. Per cui, il programma in oggetto, se per qualche motivo lo trova occupato (il file da scriverci è lock, ad esempio), ci ritenta una seconda volta a riversarci i dati. Se non ci riesce, amen.
    - L'altro programma, che invece ha l'interfaccia grafica, si gestisce lui il "problema" (non con una label ovviamente, cmq se lo gestisce).

    Vi ringrazio tutti per le risposte.

    Buona serata.
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Ci sono anche altre imprecisioni o cose superflue.

    jockerfox ha scritto:


    StringBuilder theBufToFile = new StringBuilder("");
    Non hai bisogno di passare la stringa vuota al costruttore per inizializzare lo StringBuilder.

    ---

    jockerfox ha scritto:


    theBufToFile.Append(ValForFile[i] + "-");
    Già che stai usando uno StringBuilder, adoperalo fino in fondo.
    Puoi scrivere:
    theBufToFile.Append(ValForFile[i]).Append("-");
    Ma probabilmente in questo caso risolveresti prima con
    string.Join("-", ValForFile)
    ---

    jockerfox ha scritto:


    for (int i = 1; i <= ValForFile.Count; i++)
    Sembra tu stia accedendo a una lista o a un array, però il tuo indice varia da 1 (quindi saltando lo zero) fino al Count: sei sicuro di non tralasciare qualche valore?

    ---

    jockerfox ha scritto:


    if (Save_aData(ref theBufToFile) == false)
    Tutte le volte che vedo una variabile passata con ref ho i brividi: la maggior parte viene fatta per scopi o con modi errati.
    Se fosse per me, quella parola chiave la eliminerei dal linguaggio. Lascerei tutt'al più out e basta.

    ---

    jockerfox ha scritto:


    Thread.Sleep(100);
    Piuttosto che stabilire un tempo di attesa per fare un secondo (e unico) solo tentativo, meglio definire dei "retry", quindi dei tentativi di scrittura con numero adeguato (quello sì) trasformando il tempo unico in un intervallo di attesa tra un tentativo e l'altro, magari modulandolo progressivamente (prima un tempo basso, poi man mano che si fanno tentativi aumentarlo sempre più).
    Per esigenze di questo tipo, potresti usare Polly.


    Ciao!
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    StringBuilder theBufToFile = new StringBuilder("");
    Giusta osservazione.
    theBufToFile.Append(ValForFile[i]).Append("-");
    Giusta osservazione. Corretto.
    string.Join("-", ValForFile)
    E' corretto ma uso .Append
    for (int i = 1; i <= ValForFile.Count; i++)
    Sembra tu stia accedendo a una lista o a un array, però il tuo indice varia da 1 (quindi saltando lo zero) fino al Count: sei sicuro di non tralasciare qualche valore?
    E' un dictionary, che come Key parte da 1. Per cui va bene 1.
    Thread.Sleep(100);
    Non c'è motivo di fare svariati tentativi ad oltranza.. se lo trovo in lock, c'è un motivo solo: è l'altro mio programma che lo sta leggendo. E siccome come detto @Rubik: su HDD datato 10MB di testo vengono salvati 0.1secondi
    ed il mio è pochi bytes.. 1 decimo di secondo è più che sufficiente perché l'altro mio programma lo legga e lo rilasci..

    Cmq grazie per le correzioni.


    Dalla via che ci siamo, mi sarei aspettato anche la seguente correzione (a meno che non si possa fare diversamente, per cui avrei fatto bene, ma dubito fortemente):
    bolTrash = Save_aData(ref theBufToFile); //Salvo e dimentico l'esito del salvataggio
    bolTrash come si evince dalla parola è un valore booleano da gettare, cioè lo uso perché il compilatore mi darebbe errore (Save_aData ritorna un booleano).
    Se la memoria non mi inganna, mi pare che una volta si usasse la seguente sintassi: (void) Save_aData(ref theBufToFile);
    C# non me lo accetta... per cui il nuovo c#8 (beh, ma anche vecchio visto che a breve esce il c#9) come vuole che si gestisca una chiamata ad una funzione che ha un valore di ritorno ma che in alcuni casi (come questo) non ci interessa niente del suo valore di ritorno ?
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    jockerfox ha scritto:


    E' corretto ma uso .Append
    Intendevo ovviamente al posto di .Append e di tutto lo StringBuilder, che a quel punto non servirebbe.

    Il codice rivisto:
    
    var theTextToFile = String.Join("-", ValForFile.Values.ToArray());
    if (!Save_aData(theTextToFile))
    {
      Thread.Sleep(100);
      Save_aData(theTextToFile)
    }
    

    jockerfox ha scritto:


    E' un dictionary, che come Key parte da 1. Per cui va bene 1.
    Diciamo che avere un dizionario in cui le chiavi sono ordinate progressivamente da 1 senza buchi e la ricerca avviene per chiave, con maggiore lentezza legata all'ordinamento degli inserimenti e delle ricerche non mi sembra abbia molto senso, ma lo prendiamo così...

    jockerfox ha scritto:


    bolTrash = Save_aData(ref theBufToFile); //Salvo e dimentico l'esito del salvataggio
    Se il valore di ritorno non ti serve, non sei costretto a leggerlo.
    Quando mai c'è stata la "costrizione" di dover assegnare il valore di ritorno di un metodo per forza a una variabile?
    Vedi l'esempio di codice all'inizio della risposta.

    jockerfox ha scritto:


    Se la memoria non mi inganna, mi pare che una volta si usasse la seguente sintassi: (void) Save_aData(ref theBufToFile);
    C# non me lo accetta... per cui il nuovo c#8 (beh, ma anche vecchio visto che a breve esce il c#9) come vuole che si gestisca una chiamata ad una funzione che ha un valore di ritorno ma che in alcuni casi (come questo) non ci interessa niente del suo valore di ritorno ?
    Come predetto, anche se un metodo ha un valore di ritorno, non è necessario leggerlo, salvarlo o utilizzarlo.
    Se comunque non è significativo, basta appunto mettere void al posto del tipo del valore di ritorno nella dichiarazione del metodo (che immagino sia bool).

    Questo valeva già da C# versione 0.1.
    
    public void Save_aData(string data)
    {
      // TODO
    }
    
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Mi hai convinto, ora uso join (mi ritrovo il carattere "-" all'inizio invece che in fondo, ma non è un problema. L'altra applicazione se la gestisce già correttamente .

    bolTrash = Save_aData(ref theBufToFile); //Salvo e dimentico l'esito del salvataggio corretto semplicemente con Save_aData(ref theBufToFile);
    Mannaggia.. bastava solo non mettere niente

    Uso un array (quando ricevo i dati) e non un dictionary, che non ha senso. Resta d'obbligo la Dictionary perché la lettura delle richieste (mi torna troppo comodo..).

    Grazie per tutte le dritte.
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    jockerfox ha scritto:


    Mi hai convinto, ora uso join (mi ritrovo il carattere "-" all'inizio invece che in fondo, ma non è un problema. L'altra applicazione se la gestisce già correttamente .
    Il carattere separatore "-" viene inserito tra un valore e l'altro: non è all'inizio della stringa né alla fine.

    Certo, a meno che tu non abbia un primo valore "indesiderato" (es. una stringa vuota), magari l'elemento che corrisponde alla posizione e/o alla chiave "zero", che è il sospetto segnalato nelle prime risposte in riferimento all'indice usato nel ciclo che partiva da 1.
  • Re: Il System.IO.File.WriteAllText dalla Doc sembra che usa lock automaticamente

    Alka ha scritto:


    jockerfox ha scritto:


    E' un dictionary, che come Key parte da 1. Per cui va bene 1.
    Diciamo che avere un dizionario in cui le chiavi sono ordinate progressivamente da 1 senza buchi e la ricerca avviene per chiave, con maggiore lentezza legata all'ordinamento degli inserimenti e delle ricerche non mi sembra abbia molto senso, ma lo prendiamo così...
    Se Dictionary viene scelto per le sue peculiarità, va bene, altrimenti si preferisce List.
    List in combinazione con Tuple, permette di fare operazioni ricorsive su combinazioni di liste, con un'efficienza non eguagliabile da codice equivalente scritto in C#.
Devi accedere o registrarti per scrivere nel forum
12 risposte