Autor Beitrag
Andy0019
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Fr 20.11.09 18:55 
Hallo,
habe folgendes Problem:

Programm Info:
--------------
Ich habe ein BackupDir ,ein TestDir und noch ein Log file....
Ich starte den FileSystemWatcher....
wenn ich jetzt was in das TestDir kopiere sollte er mir
über das Created-Event das neue file
in den BackupDir Ordner Kopieren...

Da das ja mal dauern kann hab ich eine QueneList in der die files dann in der FileProcessor Klasse
über einen Thread Kopiert werden...
Mein Problem ist jetzt das ab und zu alles super klappt
aber manchmal Kopiert er einfach ein file nicht oder lässt von 10 stück 3 weg...
oder kopiert ein einzelnes sogar gar nicht....

Mein Log file sagt auch das er anscheinend wärend der copy Funktion abgebrochen wird und so lässt er das file aus...
...aber wie kann ich das Problem beheben.
Im Debugging modus gibt es absolut keine Probleme alles läuft immer 100%.

Schon mal danke für jede Hilfe.....
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
FileProcessor class:
--------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace AndyWatcher
{
    public class FileProcessor
    {
        private Queue<string> workQueuePath;
        private Queue<string> workQueueName;
        private Thread workerThread;
        private EventWaitHandle waitHandle;
        private string destination;
        public StreamWriter Logfile;

        public string set_destination
        {
            set {destination = value;}
        }

        public FileProcessor()
        {
            string Date = DateTime.Now.ToShortDateString();
            string Time = DateTime.Now.ToShortTimeString();
            if (!File.Exists(@"c:\AndyLog" + Date + Time.Replace(":"" ") + ".txt"))
            {
                Logfile = new StreamWriter(File.Create(@"c:\AndyLog" + Date + Time.Replace(":"" ") + ".txt"));
            }
            else
            {
                Logfile = new StreamWriter(@"c:\AndyLog" + Date + Time.Replace(":"" ") + ".txt");
            }
            Logfile.WriteLine("Programm Start:");
            //Logfile.Close();
            Logfile.AutoFlush = true;
            workQueuePath = new Queue<string>();
            workQueueName = new Queue<string>();
            waitHandle = new AutoResetEvent(true);
        }

        #region Enquene File String

        public void QueueInput(FileSystemEventArgs e)
        {
            string SPath = e.FullPath;
            string SName = e.Name;
            workQueuePath.Enqueue(SPath);
            workQueueName.Enqueue(SName);

            // Initialize and start thread when first file is added
            if (workerThread == null)
            {
                workerThread = new Thread(new ThreadStart(Work));
                workerThread.Start();
                Logfile.WriteLine("Start NEW Thread......Path: "+SPath+" Name: "+SName);
            }

            // If thread is waiting then start it
            else if (workerThread.ThreadState == ThreadState.WaitSleepJoin)
            {
                Logfile.WriteLine("Start Waiting Thread......");
                waitHandle.Set();
            }
        }

        #endregion

        #region Progress Files

        private void Work()
        {
            lock (this)
            {
                while (true)
                {
                    Logfile.WriteLine("Start Retriving Path");
                    string Path = RetrieveFilePath();
                    Logfile.WriteLine("Start Retriving Name");
                    string Name = RetrieveFileName();
                    if (Path != null || Name != null)
                    {
                        Logfile.WriteLine("Start Progress File Method.....Path: " + Path + " Name: " + Name);
                        ProcessFile(Path, Name);
                    }
                    else
                    {
                        // If no files left to process then wait
                        Logfile.WriteLine("Wait for Work.....Path: " + Path + " Name: " + Name);
                        waitHandle.WaitOne();
                    }

                }
            }
        }

        #endregion

        #region Dequene File Path/Name

        private string RetrieveFilePath()
        {
            Logfile.WriteLine("Path_Retriving.....");
            if (workQueuePath.Count > 0)
                return workQueuePath.Dequeue();
            else
                return null;
        }

        private string RetrieveFileName()
        {
            Logfile.WriteLine("Name_Retriving.....");
            if (workQueueName.Count > 0)
                return workQueueName.Dequeue();
            else
                return null;
        }

        #endregion

        #region File Job

        private void ProcessFile(string Path,string Name)
        {
            try
            {
                lock (this)
                {
                    if (Directory.Exists(Path))
                    {
                        Logfile.WriteLine("is Directory......" + Path);
                        Directory.CreateDirectory(destination + Name);
                    }
                    else if (File.Exists(Path))
                    {
                        Logfile.WriteLine("is File......" + Path);
                        CopyFile(Path, destination + Name);
                        Logfile.WriteLine("Copy Finished (Line:110): " + Name);
                    }
                }
            }
            catch
            {
            }
        }

        private void CopyFile(string source, string dest)
        {
            Logfile.WriteLine("Copy Started (Line:120)");
            using (FileStream sourceStream = new FileStream(source, FileMode.Open))
            {
                Logfile.WriteLine("1");
                byte[] buffer = new byte[64 * 1024]; // Change to suitable size after testing performance
                Logfile.WriteLine("2");
                using (FileStream destStream = new FileStream(dest, FileMode.Create))
                {
                    Logfile.WriteLine("3");
                    int i;
                    while ((i = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        destStream.Write(buffer, 0, i);
                        Logfile.WriteLine("Copying...... (Line:130)"+sourceStream.Position+" von "+sourceStream.Length);
                        //OnProgress(sourceStream.Position, sourceStream.Length);
                    }
                }
            }
        }

        public void endstream()
        {
            Logfile.Close();
            
        }
        #endregion
    }
}



LogFile:
--------
Start Retriving Path
Path_Retriving.....
Start Retriving Name
Name_Retriving.....
Start Progress File Method.....Path: E:\testdir\5 - Kopie.pdf Name: 5 - Kopie.pdf
is File......E:\testdir\5 - Kopie.pdf
Copy Started (Line:120)
Copying...... (Line:130)65536 von 358733
Copying...... (Line:130)131072 von 358733
Copying...... (Line:130)196608 von 358733
Copying...... (Line:130)262144 von 358733
Copying...... (Line:130)327680 von 358733
Copying...... (Line:130)358733 von 358733
Copy Finished (Line:110): 5 - Kopie.pdf
Start Retriving Path
Path_Retriving.....
Start Retriving Name
Name_Retriving.....
Wait for Work.....Path: Name:
Start Waiting Thread......
Start Retriving Path
Path_Retriving.....
Start Retriving Name
Name_Retriving.....
Start Progress File Method.....Path: E:\testdir\6 - Kopie.pdf Name: 6 - Kopie.pdf
is File......E:\testdir\6 - Kopie.pdf
Copy Started (Line:120) <-Here is something wrong!
Start Retriving Path
Path_Retriving.....
Start Retriving Name
Name_Retriving.....
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Fr 20.11.09 21:36 
:welcome:

Da wird wohl an der markierten Stelle eine Exception aufgetreten sein - dass du davon nichts mitbekommst, ist bei einem leeren catch-Block kein Wunder...
Es könnte an einer Race Condition liegen - der Worker-Thread gelangt in eine Zustand, in dem die erste Queue ein Item, die zweite aber keines hat. Das passiert dadurch, dass dein Locking völlig falsch ist: Du musst auf beiden Threads locken, wenn du gemeinsame Ressourcen benutzt (aber auch nicht mehr). Also einen gemeinsamen Lock um die beiden Enqueues und einen um die vier Zeilen, die die beiden RetrieveX-Funktionen aufrufen, ansonsten keinen.

Da die beiden Queues ja immer gleich lang sind, würde ich sie übrigens in eine zusammenfassen. Das macht den Code ein wenig einfacher und hätte diese Race Condition verhindert - ganz ohne Locking könnten aber trotzdem noch andere auftreten.

_________________
>λ=
Andy0019 Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Fr 20.11.09 23:53 
Hallo,

Danke für die schnelle Antwort....

Ok hab die Locks dort hin wo sie hingehören:) --->Danke für den tipp...
bin grad am lernen und das Chapter mit den Locks und Threads hab ich noch nicht so 100% verstanden.
wuste nur das das Problem dran liegen könnte aber nicht wie ich sie richtig setze.

tja und kaum macht man ein Exeption ex in den catch Blog schon bekommt man eine Fehlermeldung. :)
hatte ich noch nicht rein weil ich ja problemlos Debugen konnte....

jetzt bekomme ich folgende Meldung und mir wird schon einiges klar....

Zitat:
"The process cannot access the file D:\testdir\test.mp3 ...
because it is being used by another process...."


Das bedeutet wohl das bei großen files oder je nach Trägheit des Systems
er mit dem Kopieren ins testdir noch nicht fertig
und da will der 2. Process schon das File ins backupdir Kopieren....
tja und da taucht dann das Problem auf.....

-irgendeine idee wie ich warte bis es fertig kopiert hat
und dann erst anfange mit dem Wegkopieren?!?!?

-maybe reicht es nicht mit fileinfo zu prüfen ob es vorhanden ist,
denn es kann ja schon erzeugt sein obwohl es noch nicht fertig kopiert ist oder?!?!?

cu Andy

PS: Ich werd sicher in Zukunft mehr Fragen stellen mach ja grad mein MCTS 70-536 Buch durch... :)
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 21.11.09 00:22 
Wenn du auf den anderen Prozess keinen Einfluss hast, gibt es da imho keine Patentlösung. Ich würde bei Fehlschlagen den Dateipfad einfach wieder in die Queue werfen und bei einer gewissen Zahl von Fehlversuchen die Datei verwerfen.

_________________
>λ=