Laden...

Verschiedene Timer - selbiges .Elapsed Event?

Erstellt von schuppsl vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.877 Views
S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 7 Jahren
Verschiedene Timer - selbiges .Elapsed Event?

Hallo zusammen.
Das Programm soll Dateien von A nach B kopieren, und nach dem Kopieren in einen Unterordner verschieben.
Dazu habe ich eine Windows Form, welches ein Datagridview enthält. In diesem kann man Quelle, Ziel und die Zeit eintragen in der das Programm von Quell nach Zielordner kopieren soll. Also z.B. alle 90 Sekunden.

Die verschiedenen Einträge speichere ich in einer XML Datei, welche ich per DataSet.ReadXml in ein DataSet in die erzeugte DataTable einlese.
Hier habe ich nun alle Pfade und den Intervall verfügbar.

Auf Knopfdruck sollen nun alle "Jobs" gestartet werden. Für jeden Job wird ein extra Timer gestartet.
Für jeden Timer gibt es dasselbe Event beim Auslösen.
Im Event wird festgestellt, welcher Timer das ist und anhand dessen die entsprechenden Dateien kopiert.

Das sieht so aus:

Beim Start, XML einlesen, für DataGridView die Source setzen, eine DataTable wird im DataSet automatisch erzeugt:


EinstellungenDataSet.ReadXml(filePath);
dataGridView1.DataSource = EinstellungenDataSet;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
dataGridView1.DataMember = "ToCopy";     

Nun sind alle Daten in der DataTable, Namens "ToCopy".

Gestartet wird das Ganze so:


foreach (DataRow row in EinstellungenDataSet.Tables[0].Rows)
{
if (rd[i] != null) { rd[i].disposeTimer(); rd[i] = null; }
.....
....
....
rd[i].time = row["time"].ToString();
....
....
rd[i].makeNewTimer();
rd[i].rTimer.Elapsed += rTimer_Elapsed;


....
...
...
 public void makeNewTimer()
        {
            rTimer = new System.Timers.Timer();
            rTimer.AutoReset = true;            
        }
...
...


Also für jeden Eintrag wird ein neuer Timer erstellt mit der eigenen Intervallzeit.

Das Elapsed Event sieht so aus:



void rTimer_Elapsed(object sender, ElapsedEventArgs e)
{            
//Welcher Timer?
 System.Timers.Timer myTimer= ((System.Timers.Timer)sender);
...
...
//Quell-und Zielpfad festlegen, Dateien im Quellpfad auflisten und jede Datei kopieren:
...
...
fileName = System.IO.Path.GetFileName(s);
destFile = System.IO.Path.Combine(zielPfad, fileName);
...
...
System.IO.File.Copy(s, System.IO.Path.Combine(archivPfad, fileName));
System.Threading.Thread.Sleep(20);
System.IO.File.Move(s, destFile);
System.Threading.Thread.Sleep(20);
...
...
...
usw.


Das Ganze wird ein einer Klasse gekapselt.

Das Ganze funktioniert ziemlich gut und läuft seit Monaten zuverlässig.
Gestern allerdings hatte ich ein Problem.
Ich habe zwei neue Einträge erstellt.
Quelle ist diesselbe, Ziele sind andere. Intervallzeit war gleich eingestellt auf 90 Sekunden.

(Habe es soweit umprogrammiert, dass man angeben kann, ob die Quelldateien bleiben sollen)
Also der 1. neue Eintrag kopiert von A nach B, lässt die Dateien aber im Quellverzeichnis.
2. neue Eintrag kopiert von A nach B2, verschiebt die Quelldateien aber ins Archiv Verzeichnis.

Soweit so gut.
Nach ca. 1 Stunde hatte ich gestern auf 16 Cores (vserver) 100% Auslastung - ausgelöst durch mein Programm.

Da es bisher lief, nehme ich an, dass es an den zwei neuen Einträgen liegt.
Bzw. es liegt wohl an:

  1. an meiner Architektur und
  2. daran, dass das Programm gleichzeitig (nach 90 sek), auf diesselben Dateien zugreift und diese einmal kopieren und andererseits verschieben möchte.
    Kann das sein?

Auch wenn das Timer Event immer dasselbe ist, ist es jedoch jeweils ein anderer Timer und ein anderer Thread.

Die Quelle, Ziel und Archiv sind alle auf einem entfernten Freigabeverzeichnis:
Quelle: \Freigabe\share\daten
Ziel: \Freigabe\share\daten\ Ziel - Verzeichnis
Archiv: \Freigabe\share\daten\Archiv

Aber auch wenn das Programm gleichzeitig auf die Dateien zugreift, sollte es sich doch nicht so verschlucken, dass es die CPU Last so in die Höhe treibt?
Hat jemand eine Erklärung?

Vielen Dank im Voraus-

16.834 Beiträge seit 2008
vor 7 Jahren

Gut, woran das 100% CPu Problem liegt; das kann hier ja niemand via Ferndiagnose sagen - nur vermuten oder ganz einfach nur raten.

Bezüglich System.Timers.Timer ist es so, dass es zwei Modi gibt wobei der eine in jedem Event nen anderen Thread hat und der andere nicht.
Ich finde das aber alles (Umsetzung) sehr schmutzig und wirkt eher gebastelt 😉

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 7 Jahren

Vielen Dank.
Dann muss ich mal die Modi anschauen.
Wie kann man sowas "ungebastelt" umsetzen?

16.834 Beiträge seit 2008
vor 7 Jahren

Die Art und Weise hier hat das Grundproblem, dass sich die Events aufschaukeln können.
Wenn eine Aktion bei Dir länger braucht als der Delay zwischen zwei Timern (alle 90 Sekunden startet was, aber es braucht jeweils 100 Sekunden), dann knallt Dir schon an den Grundzügen um die Ohren.

Die Art und Weise hier ist weiterhin überhaupt nicht abstrahiert, sodass sie auch nicht annähernd testbar ist.
Wenn bei Dir etwas abstürzt, dann weißt Du auch nicht, wo Du aktuell im Prozess bist.
Was diese Sleeps tun und wieso Du das genutzt hast: keine Ahnung.

Das Grundproblem des Timers lässt sich über ein Frameworks wie Hangfire oder Quartz.NET lösen.
Das Thema Pooling zB. über Elemente wie TPL Pipelines.

Und dann kommt es drauf an, ob Du mit lokalen Daten arbeitest oder via SMB Daten verwaltest (also Netzwerk etc...).

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 7 Jahren

Also Quell und Zieldateien sind entweder im Hauseigenen oder externen Netzlaufwerk.
Genauso wie du es beschreibst, dachte ich es mir und mMn nach ist genau das passiert: Die Events haben sich aufgeschaukelt und dann irgendwo im Nirwana gelandet.

Dann muss ich mir mal die genannten Frameworks anschauen. Vielen Dank.

3.825 Beiträge seit 2006
vor 7 Jahren

Ein guter Tipp zum schnellen Kopieren von Dateien :

QuickIO.NET - Performante Dateioperationen

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 7 Jahren

Alles klar, vielen Dank.

16.834 Beiträge seit 2008
vor 7 Jahren

.. und Du musst zB Dir selbst nen Locking-Mechanismus schreiben, sodass ein Event auf X nicht zwei mal zeitgleich laufen kann.

S
schuppsl Themenstarter:in
789 Beiträge seit 2007
vor 7 Jahren

Ja!