unde să dispun StreamWriter dacă am nevoie de ea în timpul întreaga viață a aplicației?

Where to dispose StreamWriter if I need it during entire application lifetime? I'm going to dispose it in destructor, will that work? I have to dispose to flush data, and I don't want to use AutoFlush feature because from msdn: "You can get better performance by setting AutoFlush to false, assuming that you always call Close (or at least Flush) when you're done writing with a StreamWriter."

Deci ar trebui să Dispose în destructor ca în codul de mai jos?

class Log
{
    private static StreamWriter swLog = new StreamWriter("logMAIN.txt");

    static ~Log()
    {
        swLog.Dispose();
    }

    public static void Push(LogItemType type, string message)
    {
        swLog.WriteLine(type + " " + DateTime.Now.TimeOfDay + " " + message);
    }
}

upd instead of Dispose i meant to call Close but it is not improtant in this case because they seems doing exactly the same.

0
Dacă faceți acest lucru pentru logare, luați în considerare utilizarea cadrelor de urmărire existente (una care face parte din .Net Framework sau una dintre cele mai externe, cum ar fi Log4Net), care deja au rezolvat toate problemele pe care le întâmpinați și le veți descoperi în viitor , rotația jurnalului, eșecuri IO, extensibilitate ...).
adăugat autor Alexei Levenkov, sursa
Doar utilizați File.WriteAllText și nu vă deranjați cu StreamWriter .
adăugat autor Bali C, sursa

2 răspunsuri

Se pare că vă bazați decizia de a nu elimina unele informații despre performanță de la MSDN. Nu este locul unde aș începe.

Aveți dovezi că utilizarea funcției AutoFlush vă provoacă probleme de performanță semnificative ?

Ați considerat că atenuarea acestor probleme de performanță este diferită, de ex. având un singur fir de scriere la StreamWriter , fie automat de spălare, fie în mod periodic spălare la fiecare 20 de secunde sau altceva?

Nu ne-ați spus ce fel de aplicație scrieți, vă gândiți - aceasta poate face o diferență semnificativă în ceea ce privește cât de mult știi despre oprire.

Rețineți, de asemenea, că codul pe care l-ați dat nu este sigur pentru a începe. S-ar putea să ajungeți folosind StreamWriter din mai multe fire simultan; Mă îndoiesc că StreamWriter este special conceput pentru acest scenariu.

0
adăugat
unele jurnale sunt multithreaded, în acest caz folosesc lock (this) în interiorul metodei Push . Cred ca nu folosesc fire de fundal (dar folosesc Tasks ). Multumesc Jon Cred ca voi folosi doar AutoFlush pana cand aceasta devine o problema
adăugat autor javapowered, sursa
este doar o aplicație consola
adăugat autor javapowered, sursa
de ce nu pot să implementez un lucru atât de simplu: "păstrați fluxul deschis până când clasa exterioară este dispusă.
adăugat autor javapowered, sursa
aplicația este utilizată pentru tranzacționarea cu HFT. bine da am ieșire numai atunci când închiderea aplicației :) sau ce vrei să spui prin puncte de ieșire ?
adăugat autor javapowered, sursa
Am multe jurnale diferite în aplicațiile mele, unele dintre ele, deoarece acestea sunt folosite doar dintr-un singur fir. Probabil caracteristica AutoFlush va fi bine pentru mine, dar pentru că nu am nevoie de jurnal imediat m-am gândit să nu o folosesc. Nu există nici un motiv pentru mine să folosesc AutoFlush și a fost dezactivat implicit în .NET, așa că am decis să folosesc scenariul "implicit".
adăugat autor javapowered, sursa
@javapowered: "Nu există niciun motiv pentru mine să utilizez AutoFlush" - bine, în afară de faptul că doriți să vă asigurați că nu pierdeți niciun jurnal chiar dacă aplicația dvs. este închisă? Încă nu ați explicat ce aplicație scrieți și dacă aveți un punct de ieșire bine definit ...
adăugat autor Jon Skeet, sursa
@ javapowered: Poți. Dar nu ne-ați spus ce aplicație este aplicație web, client bogat etc. Dacă puteți spune momentul potrivit pentru a dispune de jurnalele dvs., atunci sigur - aruncați-le apoi.
adăugat autor Jon Skeet, sursa
@ iavapowered: Bine, în sfârșit, niște informații. Și aveți mai multe fire, sau este doar un fir? Dacă aveți mai multe fire, sunt oricare dintre firele de fundal? Dacă poate să eliminați totul curat pe măsură ce ieșiți, aceasta va fi cea mai ușoară abordare ... deși înseamnă că veți găsi probabil IDisposable care se ascund tot timpul prin codul dvs., doar de dragul logării. Te-aș îndemna să mă gândiți cel puțin la ...
adăugat autor Jon Skeet, sursa

Problema este într-adevăr modul în care StreamWriter este inițializat. Folosind un obiect obișnuit ca acesta

using (var logger = new Log())
{
    app.Run();
}

StreamWriter poate fi încă un câmp static în clasa Log , dar este inițializat și dispus în momente cunoscute în timp, mai degrabă decât folosind un inițializator static.

Pentru ca aceasta să funcționeze, va trebui să vă lăsați să logați clasa să implementați interfața IDisposable și să eliminați StreamWriter în metoda Dispose

class Log: IDisposable
{
    private static StreamWriter swLog;

    public Log()
    {
       swLog = new StreamWriter("logMAIN.txt");
    }

    public void Dispose()
    {
        swLog.Dispose();
    }

    public static void Push(LogItemType type, string message)
    {
        swLog.WriteLine(type + " " + DateTime.Now.TimeOfDay + " " + message);
    }
}

De asemenea, rețineți modul în care Log va fi dispus chiar dacă se va trage o excepție.

0
adăugat
și dacă am mai multe jurnale (sau duzini) diferite aș scrie o mulțime de imbricate folosind blocurile ?
adăugat autor javapowered, sursa
@JonSkeet meu rău, să eliminăm doar static de la destructor și să presupunem că această clasă este folosită doar de la un fir ... hm totuși am nevoie de versiune multithreaded prea
adăugat autor javapowered, sursa
@vidstige: Codul original nu se compilează, deoarece nu există un finalizator static. Dar sugerând o soluție care mută o variabilă statică în construcții nu este un răspuns bun, IMO.
adăugat autor Jon Skeet, sursa
@vidstige: De fapt, e mai rău acum. Acum, dacă aveți două blocuri folosind creând instanțe separate în fire diferite, puteți să eliminați StreamWriter într-un fir în timp ce încercați să îl utilizați în altul. Ouch. Evident, dacă aplicația dvs. este suficient de simplă pentru a avea un punct de ieșire bine controlat, întrebarea este banală. Mi-aș imagina că nu este cazul, deși OP nu a spus ce fel de aplicație este asta.
adăugat autor Jon Skeet, sursa
@javapowered: Acum presupuneți că finalizatorul dvs. va fi executat înainte de finalizarea pentru fluxul de bază. Nu există nicio garanție pentru asta. Practic, nu ar trebui să utilizați finalizatori în acest caz.
adăugat autor Jon Skeet, sursa
Nu ați explicat modul în care StreamWriter va fi "inițializat și eliminat în momente cunoscute în timp" - unde eliminarea este punctul important aici.
adăugat autor Jon Skeet, sursa
@Jon Aceasta este și problema din codul original. Amintiți-vă că finalizatorul rulează în firul propriu. Întrebarea privind accesul din mai multe fire nu se referă decât vag la întrebarea când să dispună StreamWriter. Presupunerea mea este opusul pe care l-ai ghicit, aplicația are un punct de ieșire bine definit.
adăugat autor vidstige, sursa
@ Sincer adevărat. acea parte este, sperăm, un pic mai clară după editare
adăugat autor vidstige, sursa
da, de ce nu? Sau creați o clasă nouă care are o listă de jurnale care se elimină când este dispusă. O clasă, o responsabilitate.
adăugat autor vidstige, sursa