none
Locking object - wie handhaben? RRS feed

  • Frage

  • Hallo,
    ich habe eine Logging Klasse erstellt.
    Schreibe Files, es kann vorkommen, dann ein anderer Prozess auch schreibt.
    Abhilfe ist das locking object.
    Reicht das innerhalber der Funktion oder muss es als Member der Klasse sein.
    Oder müsste ich das so machen     
              private static object Locking = new object();
    // ---- innerhalb der Funktion    
    object locking = new object();
    lock (locking)
    {
     if (File.Exists(filename))
     {
      try
      {
       using (StreamWriter swAppend = File.AppendText(filename))
       {


    Viele Grüße Sandra
    Dienstag, 19. April 2016 17:04

Antworten

  • Hallo Sandra,

    C#s lock bringt dir gar nichts wenn mehrere Prozesse auf die selbe Datei zugreifen. lock bringt dir nur dann etwas, wenn du mehrere Threads zugleich handhaben musst. Um Probleme bei den Prozessen zu unterbinden solltest du verschiedene Dateien schreiben - eine für jeden Prozess.

    Die gesperrte Variable liegt üblicherweise in der Klasse. Das hat den Hintergrund das es zu vermeiden gilt für jeden Thread (Methodenaufruf) ein neues Objekt anzulegen. Bei mehreren Prozessen ist das aber sowieso hinfällig, da man keine Instanzen Prozessübergreifend teilen kann.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Dienstag, 19. April 2016 18:44
    Moderator
  • Hallo Sandra,

    wichtig ist, dass du immer dasselbe Object verwendest, welches du mit lock (Monitor,...) benutzt. Wenn du es innerhalb einer Klasse verwendest, werden bei zwei (oder mehreren) Instanzen deiner Klasse unter Umständen jedesmal neue verschiedene Lock-Objekte erstellt und machen den Schutzmechanismus wirkungslos.

    Falls also die Möglichkeit besteht, dass du mehrer Instanzen der Klasse verwendest, sollte das Lock-Objekt klassenweit einmalig sein, also static. Verwenden mögliche Threads alle dieselbe Instanz deiner Klasse, kann man darauf (static) verzichten, es schadet aber nicht.

    Um zu verhindern, dass in irgendeiner Methode deiner Klasse das Lock-Objekt neu zugewiesen wird, sollte es auch noch readonly deklariert werden.

    Lock (Monitor) agieren auf Ebene deiner AppDomain, sind deshalb nur wirksam innerhalb deines "Programms", dort erzeugte Threads können davon profitieren.

    Falls du mit "Prozess" wirklich verschiedene Programme meinst, kann dir (wie schon erwähnt wurde) Mutex weiterhelfen, da dies auf Betriebssystemebene angesiedelt ist und damit zwischen verschiedenen Prozessen verfügbar ist. Es muss dann natürlich sichergestellt sein, dass alle beteiligten Prozesse auch "dieselbe Tür" benutzen. Falls es sich bei dem anderen Prozess um ein (Fremd)Programm handelt, kannst du davon nicht ausgehen und es würde dir nichts bringen.

    Du kannst dein Programm aber dahingehend gestalten, dass du den Zugriff auf die gemeinsam genutzte Log-Datei in ein Try...Catch-Gerüst verpackst und entsprechend darauf reagierst (ob du z.B. exklusiven Schreibzugriff erlangen kannst.).

    Nebenbei gibt es auch synchronisierte TextWriter, dann kannst du dir meines Erachtens Lock sparen:

    public bool Schreibe(string filename, string message) { try { using ( var writer = TextWriter.Synchronized(new StreamWriter(new FileStream(filename,
    FileMode.Append, FileAccess.ReadWrite, FileShare.None), Encoding.UTF8)) ) { writer.WriteLine(message);
    return true; } } catch ( Exception ) { // Fehlerbehandlung
    return false; } }

    Falls die Schreibe-Methode fehlschlägt, könntest du z.B. den Versuch wiederholen...

    Gruß



    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Mittwoch, 20. April 2016 08:57
  • Hi Sandra,
    wie Tom bereits geschrieben hat, wirkt lock nur im Gültigkeitsbereich des Objektes, welches bei lock angegeben wurde. Das bedeutet, dass prozessübergreifend kein lock anwendbar ist. Da kann mutex genutzt werden.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Mittwoch, 20. April 2016 03:43

Alle Antworten

  • Hallo Sandra,

    C#s lock bringt dir gar nichts wenn mehrere Prozesse auf die selbe Datei zugreifen. lock bringt dir nur dann etwas, wenn du mehrere Threads zugleich handhaben musst. Um Probleme bei den Prozessen zu unterbinden solltest du verschiedene Dateien schreiben - eine für jeden Prozess.

    Die gesperrte Variable liegt üblicherweise in der Klasse. Das hat den Hintergrund das es zu vermeiden gilt für jeden Thread (Methodenaufruf) ein neues Objekt anzulegen. Bei mehreren Prozessen ist das aber sowieso hinfällig, da man keine Instanzen Prozessübergreifend teilen kann.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Dienstag, 19. April 2016 18:44
    Moderator
  • Hi Sandra,
    wie Tom bereits geschrieben hat, wirkt lock nur im Gültigkeitsbereich des Objektes, welches bei lock angegeben wurde. Das bedeutet, dass prozessübergreifend kein lock anwendbar ist. Da kann mutex genutzt werden.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Mittwoch, 20. April 2016 03:43
  • Hallo Sandra,

    wichtig ist, dass du immer dasselbe Object verwendest, welches du mit lock (Monitor,...) benutzt. Wenn du es innerhalb einer Klasse verwendest, werden bei zwei (oder mehreren) Instanzen deiner Klasse unter Umständen jedesmal neue verschiedene Lock-Objekte erstellt und machen den Schutzmechanismus wirkungslos.

    Falls also die Möglichkeit besteht, dass du mehrer Instanzen der Klasse verwendest, sollte das Lock-Objekt klassenweit einmalig sein, also static. Verwenden mögliche Threads alle dieselbe Instanz deiner Klasse, kann man darauf (static) verzichten, es schadet aber nicht.

    Um zu verhindern, dass in irgendeiner Methode deiner Klasse das Lock-Objekt neu zugewiesen wird, sollte es auch noch readonly deklariert werden.

    Lock (Monitor) agieren auf Ebene deiner AppDomain, sind deshalb nur wirksam innerhalb deines "Programms", dort erzeugte Threads können davon profitieren.

    Falls du mit "Prozess" wirklich verschiedene Programme meinst, kann dir (wie schon erwähnt wurde) Mutex weiterhelfen, da dies auf Betriebssystemebene angesiedelt ist und damit zwischen verschiedenen Prozessen verfügbar ist. Es muss dann natürlich sichergestellt sein, dass alle beteiligten Prozesse auch "dieselbe Tür" benutzen. Falls es sich bei dem anderen Prozess um ein (Fremd)Programm handelt, kannst du davon nicht ausgehen und es würde dir nichts bringen.

    Du kannst dein Programm aber dahingehend gestalten, dass du den Zugriff auf die gemeinsam genutzte Log-Datei in ein Try...Catch-Gerüst verpackst und entsprechend darauf reagierst (ob du z.B. exklusiven Schreibzugriff erlangen kannst.).

    Nebenbei gibt es auch synchronisierte TextWriter, dann kannst du dir meines Erachtens Lock sparen:

    public bool Schreibe(string filename, string message) { try { using ( var writer = TextWriter.Synchronized(new StreamWriter(new FileStream(filename,
    FileMode.Append, FileAccess.ReadWrite, FileShare.None), Encoding.UTF8)) ) { writer.WriteLine(message);
    return true; } } catch ( Exception ) { // Fehlerbehandlung
    return false; } }

    Falls die Schreibe-Methode fehlschlägt, könntest du z.B. den Versuch wiederholen...

    Gruß



    • Als Antwort markiert Sandra Bauer Mittwoch, 20. April 2016 16:05
    Mittwoch, 20. April 2016 08:57