Avatar billede idiotbarn Nybegynder
09. oktober 2005 - 13:22 Der er 16 kommentarer og
1 løsning

Logfil (Textfil)

Jeg er ved at lave et system hvor jeg gerne vil logge forskellligt aktivitet i en tekstfil. Jeg har nu to problemer...Jeg får en fejl med at jeg ikke kan få adgang til tekstfilen fordi den bliver brugt af en anden app.
Så 1):  Hvad er fejlen i koden.
2): Jeg render vel ind i et problem hvis 2 personer forsøger at skrive til tekstfilen samtidig? Hvordan omgåes det bedst, og er det en dårlig metode at gøre det på denne måde?


KODE:
private bool DoWrite(String FullPath, String Content,bool CreateFile)

        {

            String OldText="";

            bool success=true;

            if(!File.Exists(FullPath))

            {

                if(CreateFile)

                {

                    File.Create(FullPath);

                }

                else

                {

                    success=false;

                    strError="The file does not exist";

                }

            }

            else

            {

                    StreamReader SR = new StreamReader(FullPath);

                    String line;

                    while ((line = SR.ReadLine()) != null)

                        OldText+=line+"|";

                   

                    SR.Close();

            }

            if(success)

            {

                StreamWriter sw = new StreamWriter(FullPath);

                String[] arrOldText = OldText.Split('|');

                String[] arrText=Content.Split('|');



                for(int i=0; i<arrText.Length;i++)

                {

                    sw.WriteLine(arrText[i]);

                }

                sw.WriteLine("");

                sw.WriteLine("");

                for(int i=0; i<arrOldText.Length;i++)

                {

                    sw.WriteLine(arrOldText[i]);

                }

                sw.Close();

            }

                return success;

        }
Avatar billede arne_v Ekspert
09. oktober 2005 - 13:33 #1
jeg kan ikke lige umiddelbart se dit problem

men hvorfor bruger du ikke StreamWriter's mulighed for at appende til
en fil - det vil vil korte koden voldsomt ned

iøvrigt er der glimrende logging frameworks som f.eks. log4net
Avatar billede idiotbarn Nybegynder
09. oktober 2005 - 13:40 #2
append ligger teksten bagved...det er kun for at ha den i DESC order...
Jeg har ikke tænkt så meget over at bruge 3.parts kode, det var lige så meget for at kun ha det jeg vil bruge...men vil jeg ikke rende ind problemer hvis to prøver at skrive til samme tekstfil på en gang? Er der en smartere måde hvis man selv vil lave det?
Avatar billede arne_v Ekspert
09. oktober 2005 - 14:03 #3
ah - sådan - så er du nok nødt til selv at kode noget - alt færdigt appender

men din måde vil jo performe meget dårligt hvis filen bliver meget stor

hvis 2 brugere kører samme program og de skal skrive til samme fil, så får
du samtidigheds problemer

en typisk løsning ville være at lade de 2 forekomster af samme program
sende til en server og så lade den skrive til filen

ellers skal du have implementeret en låse mekanisme
Avatar billede idiotbarn Nybegynder
09. oktober 2005 - 14:09 #4
Jeg laver en ny logfil for hver dag...det er kun en logfil over fejl, og der skulle helst ikke komme så mange at det bliver et problem...
forstår ikke helt:
"en typisk løsning ville være at lade de 2 forekomster af samme program
sende til en server og så lade den skrive til filen"

er det muligt at lave en kø med hvad der skal skrives til filerne, så serveren bare gør det sideløbende mens brugeren bare bliver sendt videre?
Jeg mister vel en klasse når brugeren går væk fra en side?
Avatar billede arne_v Ekspert
09. oktober 2005 - 14:14 #5
når vi snakker ASP.NET sider, så kan du relativt nemt synkronisere
med lock keyword i C# eller det tilsvarende i VB.NET

men man kan også sagtens lave en kø
Avatar billede idiotbarn Nybegynder
09. oktober 2005 - 14:20 #6
men hvis jeg har en klasse fx

LogQue()
med en metode

AddQueue(Filnavn,Indhold)

hvor man kan tilføje et nyt element, ved jeg ikke rigtigt hvordan jeg skulle implementere at den venter på at filen er fri. Kommer brugeren ikke til at hænge indtil filen er blevet skrevet til?

Faktisk er det ikke så vigtigt at få logget ALT, jeg kunne godt lade nogen af dem smutte, men diskutionen er ret interessant
Avatar billede arne_v Ekspert
09. oktober 2005 - 14:35 #7
I september lavede jeg det her eksempel:

using System;
using System.Collections;
using System.Threading;

namespace E
{
    public abstract class Command
    {
        public abstract void Execute();
    }
    public class Test1Command : Command
    {
        private int v;
        public Test1Command(int v)
        {
            this.v = v;
        }
        public override void Execute()
        {
            Console.WriteLine("Test1 thread = " + Thread.CurrentThread.Name + " v = " + v);
        }
    }
    public class Test2Command : Command
    {
        private int v;
        public Test2Command(int v)
        {
            this.v = v;
        }
        public override void Execute()
        {
            Console.WriteLine("Test2 thread = " + Thread.CurrentThread.Name + " v = " + v);
        }
    }
    public class CommandQueue
    {
        private Queue q;
        public CommandQueue()
        {
            q = new Queue();
        }
        public void Enqueue(Command cmd)
        {
            Monitor.Enter(q);
            q.Enqueue(cmd);
            Monitor.PulseAll(q);
            Monitor.Exit(q);
        }
        public Command Dequeue()
        {
            Command cmd = null;
            do
            {
                Monitor.Enter(q);
                if(q.Count > 0)
                {
                    cmd = (Command)q.Dequeue();
                }
                else
                {
                    Monitor.Wait(q);
                }
                Monitor.Exit(q);
            } while(cmd == null);
            return cmd;
        }
    }
    public class WorkerThread
    {
        private CommandQueue cq;
        public WorkerThread(CommandQueue cq)
        {
            this.cq = cq;
        }
        public void Run()
        {
            while(true)
            {
                Command cmd = cq.Dequeue();
                cmd.Execute();
            }
        }
    }
    public class WorkerThreadPool
    {
        private WorkerThread[] wt;
        public WorkerThreadPool(int n, CommandQueue cq)
        {
            wt = new WorkerThread[n];
            for(int i = 0; i < wt.Length; i++)
            {
                wt[i] = new WorkerThread(cq);
                Thread t = new Thread(new ThreadStart(wt[i].Run));
                t.Name = "Thread-" + (i + 1);
                t.Start();
            }
        }
    }
    public class TestClass
    {
        public static void Main(string[] args)
        {
            CommandQueue qc = new CommandQueue();
            WorkerThreadPool wtp = new WorkerThreadPool(3, qc);
            qc.Enqueue(new Test1Command(1));
            qc.Enqueue(new Test2Command(2));
            qc.Enqueue(new Test1Command(3));
            qc.Enqueue(new Test2Command(4));
            Thread.Sleep(5000);
            Environment.Exit(0);
        }
    }
}
Avatar billede arne_v Ekspert
09. oktober 2005 - 14:36 #8
som er en kø der tilgåes af flere forskellige tråde

i eksempelt er det en som sætter i kø og mange som tager ud af kø

du vil have det omvendt - mange som sætter i kø og en som henter

men queue klasen er god nok
Avatar billede idiotbarn Nybegynder
09. oktober 2005 - 14:40 #9
takker...kikker lige lidt mere på Threading klassen, må indrømme jeg ikke rigtigt har undersøgt den...
Ligger du et svar?
Avatar billede arne_v Ekspert
09. oktober 2005 - 15:31 #10
gerne
Avatar billede idiotbarn Nybegynder
10. oktober 2005 - 22:39 #11
Hej igen...jeg skal lige være sikker på det jeg egentligt vil kan lade sig gøre.
Hvis jeg på siden bare smider et objekt (indeholder en filsti og et indhold) i treadpool(den er jeg ikke helt sikker på), kan brugeren frit gå videre selv om indholdet ikke er blevet skrevet endnu? så hvis der fx er en kø på 10, skal han ikke vente på at dem før ham bliver færdig før han kan komme videre? Eller bliver han nød til at vente?
Avatar billede arne_v Ekspert
10. oktober 2005 - 23:21 #12
han behøver ikke vente
Avatar billede idiotbarn Nybegynder
13. oktober 2005 - 22:59 #13
Hej arne. Hvis du gider at hjælpe mig lidt mere på vej, opretter jeg lige et spm med nogen flere point?

Jeg har været lidt rundt på forskellige sider og har prøvet at læse lidt omkring det, men er stadig temmeligt meget på bar bund.
Her er hvad jeg har nu (faktisk mest afskrift, for jeg er ikke helt klar over hvad det præcist er der sker):

Jeg har klasserne:

namespace IS.Net
{
public class LogQueue
{
    private Queue FileQueue;
       
        public LogQueue()
        {
            FileQueue = new Queue();
        }

        public void Enqueue(LogfileObjekt L)
        {
            //Låser, så ingen anden thread kan tilgå samtidig
            Monitor.Enter(FileQueue);
            FileQueue.Enqueue(L);
            //Sender signal om at låsen er blevet ændret
            Monitor.PulseAll(FileQueue);
            //Åbner for nye elementer i køen
            Monitor.Exit(FileQueue);
        }

        public LogfileObjekt Dequeue()
        {
            LogfileObjekt L = null;
            do
            {
                Monitor.Enter(FileQueue);
                if(FileQueue.Count>0)
                {
                    L = (LogfileObjekt)FileQueue.Dequeue();
                }
                else
                {
                    Monitor.Wait(FileQueue);
                }
                Monitor.Exit(FileQueue);
            }while(L==null);
            return L;
        }
    }

    public class WorkerThread
    {
        private LogQueue cq;
        public WorkerThread(LogQueue cq)
        {
            this.cq = cq;
        }
        public void Run()
        {
        while(true)
        {
            LogfileObjekt OL = cq.Dequeue();
            IS.Net.WriteLog WL = new IS.Net.WriteLog(OL);
            WL.Execute();
        }
        }

    }

    public class WorkerThreadPool
    {
        private WorkerThread[] wt;
        public WorkerThreadPool(int n, LogQueue cq)
        {
            wt = new WorkerThread[n];
            for(int i = 0; i < wt.Length; i++)
            {
                wt[i] = new WorkerThread(cq);
                Thread t = new Thread(new ThreadStart(wt[i].Run));
                t.Name = "Thread-" + (i + 1);
                t.Start();
            }
        }
    }

}








public class LogfileObjekt
    {
    String _FullPath="",_Content="";
    bool _Append,_CreateFile,_EmailNotification;
    public LogfileObjekt(String FullPath, String Content, bool Append,bool CreateFile,bool EmailNotification)
    {
        _FullPath=FullPath;
        _Content=Content;
        _Append=Append;
        _CreateFile=CreateFile;
        _EmailNotification=EmailNotification;
    }
   
    public String FullPath
    {
        get
        {
            return _FullPath;
        }
    }
    public String Content
    {
        get
        {
            return _Content;
        }
    }
   
    public bool Append
    {
        get
        {
            return _Append;
        }
        }
    public bool CreateFile
    {
        get
        {
            return _CreateFile;
        }
    }
   
    public bool EmailNotification
    {
        get
        {
            return _EmailNotification;
        }
        }
    }
   
    public class WriteLog
    {
        bool _CreateFile,_EmailNotification;
        LogfileObjekt L;

    public WriteLog(LogfileObjekt LO)
    {
        L=LO;
        if(!System.IO.File.Exists(L.FullPath))
        {
            if(!L.CreateFile)
            {
                //throw System.IO.FileNotFoundException;
            }
            else
            {
                System.IO.File.Create(L.FullPath);
            }
        }
        }

        public void Execute()
        {
            if(L.Append)
            {
                System.IO.StreamWriter w = System.IO.File.AppendText(L.FullPath);
                w.Write(L.Content);
                w.Close();
            }
            else
            {
                String OldText="";
                using(StreamReader R = new StreamReader(L.FullPath))
                    {
                        OldText=R.ReadToEnd();
                    }
                using(System.IO.StreamWriter sw = new System.IO.StreamWriter(L.FullPath))
                    {
                        sw.Write(L.Content);
                    }

            }
        }
    }





Når jeg så kalder disse inde fra login siden bruger jeg:

LogQueue LQ = new LogQueue();
IS.Net.WorkerThreadPool wtp = new IS.Net.WorkerThreadPool(1, LQ);
LQ.Enqueue(new LogfileObjekt(LogPath+"Logins\\"+Fil,Content,true,true,false));
System.Threading.Thread.Sleep(5000);
Environment.Exit(0);
Avatar billede idiotbarn Nybegynder
13. oktober 2005 - 23:02 #14
skal lige siges at jeg får en:
Server Application Unavailable
Avatar billede arne_v Ekspert
13. oktober 2005 - 23:05 #15
hvis jeg skal kigge på det så bliver det først i weekenden
Avatar billede idiotbarn Nybegynder
13. oktober 2005 - 23:07 #16
ja ja...det er helt iorden, jeg er bare taknemlig for at du overhovedet gider
Avatar billede idiotbarn Nybegynder
15. oktober 2005 - 17:47 #17
Ok. Jeg kan godt skrive til filerne hvis jeg ikke har de sidste to linier med. Så det ser ud som om det fungere...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester