Benutzer mit den meisten Antworten
Dateien gelockt öffnen, ändern, schreiben

Frage
-
Hallo Community,
Ich habe derzeit folgende XML-Datei:
<?xml version="1.0" encoding="utf-8" ?> <Root> <Counters> <Counter> <Name = "Gerade" value = "8" </Name> </Cursor> <Counter> <Name = "Ungerade" value = "77" </Name> </Cursor> <Counter> <Name = "Test" value = "1000" </Name> </Counter> </Counters> </Root>
Weiterhin habe ich eine Applikation - Zaehler.EXE, die ich drei mal öffne und eine Datei.
Counters.XML
Alle drei Applikationen greifen auf diese zu und erhöhen die Zählerstände, jeweils um 1
Idee: Den Zähler 'Test' möchte ich von allen 3 Applikationen zeitgleich um 100 Durchläufe erhöhen.
Wenn alles passt, alle durchlaufen sind, muss ich den Zählerstand 1300 haben.
Wer kann mit Tipps, für diese Testanwendung geben? Danke im Voraus.
Thread? locking? Mutex? Exclusiv öffnen?
Viele Grüße Martin
- Bearbeitet Martin Scheid Dienstag, 29. November 2016 11:38 Korrektur im XML
Antworten
-
Hi Martin,
eine weitere Möglichkeit wäre eine Inter-Process Communication.
Eine Art wäre dass du eine Server Applikation hast die die Datei ließt und schreibt d.h. die Synchronisation übernimmt und beliebig viele Client Applikationen die den Server beauftragen die Zahl zu inkrementieren.
-------
Server:
class Program { static void Send(NamedPipeClientStream client, Message data) { StreamString ss = new StreamString(client); var messageString = new JavaScriptSerializer().Serialize(data); Console.WriteLine("Send message: " + messageString); ss.WriteString(messageString); } static Message Receive(NamedPipeClientStream client) { StreamString ss = new StreamString(client); string messageString = ss.ReadString(); Console.WriteLine("Receive message: " + messageString); return new JavaScriptSerializer().Deserialize<Message>(messageString); } static void Main(string[] args) { string filePath = "SomeFile.xml"; var client = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut); try { client.Connect(); var message = new Message(); message.FilePath = filePath; Send(client, message); var response = Receive(client); var data = int.Parse(response.Data); data = data + 100; message = new Message(); message.FilePath = filePath; message.Data = data.ToString(); Send(client, message); } finally { client.Close(); } } }
Message:
public class Message { public string FilePath { get; set; } public string Data { get; set; } }
Client:
class Program { static void Send(NamedPipeClientStream client, Message data) { StreamString ss = new StreamString(client); var messageString = new JavaScriptSerializer().Serialize(data); Console.WriteLine("Send message: " + messageString); ss.WriteString(messageString); } static Message Receive(NamedPipeClientStream client) { StreamString ss = new StreamString(client); string messageString = ss.ReadString(); Console.WriteLine("Receive message: " + messageString); return new JavaScriptSerializer().Deserialize<Message>(messageString); } static void Main(string[] args) { string filePath = "SomeFile.xml"; var client = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut); try { client.Connect(); var message = new Message(); message.FilePath = filePath; Send(client, message); var response = Receive(client); var data = int.Parse(response.Data); data = data + 100; message = new Message(); message.FilePath = filePath; message.Data = data.ToString(); Send(client, message); } finally { client.Close(); } } }
StreamString:
Die Klasse kannst du von der folgenden MSDN Seite kopieren: https://msdn.microsoft.com/de-de/library/bb546085%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
-------
Welcher Ansatz für dich am Besten passt kann ich natürlich nur schwer sagen, da ich nicht genau weiß was das Ziel des ganzen ist.
Ganz nebenbei: Das XML in deinem ersten Post hat kein valides Format. Um den Client und Server Code aus diesem Post zu verwenden muss das Format natürlich valide sein, da Standard XML Klassen verwendet werden.
Quellenangaben:
Teile des Codes und die Art der Interprozess Kommunikation sind vom Beispiel auf der folgenden MSDN Seite kopiert: https://msdn.microsoft.com/de-de/library/bb546085%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
Gruß,
David
- Bearbeitet David Roller Mittwoch, 30. November 2016 21:45 Typo
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 5. Dezember 2016 09:12
- Als Antwort markiert Martin Scheid Montag, 5. Dezember 2016 18:34
Alle Antworten
-
Diese Thema wurde kürzlich erst behandelt:
- Florian
- Bearbeitet Florian Haupt Dienstag, 29. November 2016 13:49 weiterer Thread mit dem Thema
-
Hi,
ich glaub der einfachste Weg ist ein Mutex zu verwenden.
class Program { static void Main(string[] args) { var mutex = new Mutex(false, "Global\\DC9B5D68-BB56-420E-89B7-755790055769"); try { mutex.WaitOne(); // Do the file operation } finally { mutex.ReleaseMutex(); } } }
Aber mit dem Mutex ist nicht 100% sicher. Es funktioniert z.B. nicht wenn auch andere Applikationen, die den Mutex nicht überprüfen, die Datei gleichzeitig editieren.
Daneben gibt es natürlich auch noch etliche andere Möglichkeiten von exclusive öffnen, über ein Process haben der die Datei Synchronisation übernimmt bis zur Verwendung von shared Memory.
Die aufwendigere Möglichkeiten sind jedoch schwer hier als Testanwendung / Code snippet zu posten.
Gruß,
David
-
Hi Martin,
eine weitere Möglichkeit wäre eine Inter-Process Communication.
Eine Art wäre dass du eine Server Applikation hast die die Datei ließt und schreibt d.h. die Synchronisation übernimmt und beliebig viele Client Applikationen die den Server beauftragen die Zahl zu inkrementieren.
-------
Server:
class Program { static void Send(NamedPipeClientStream client, Message data) { StreamString ss = new StreamString(client); var messageString = new JavaScriptSerializer().Serialize(data); Console.WriteLine("Send message: " + messageString); ss.WriteString(messageString); } static Message Receive(NamedPipeClientStream client) { StreamString ss = new StreamString(client); string messageString = ss.ReadString(); Console.WriteLine("Receive message: " + messageString); return new JavaScriptSerializer().Deserialize<Message>(messageString); } static void Main(string[] args) { string filePath = "SomeFile.xml"; var client = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut); try { client.Connect(); var message = new Message(); message.FilePath = filePath; Send(client, message); var response = Receive(client); var data = int.Parse(response.Data); data = data + 100; message = new Message(); message.FilePath = filePath; message.Data = data.ToString(); Send(client, message); } finally { client.Close(); } } }
Message:
public class Message { public string FilePath { get; set; } public string Data { get; set; } }
Client:
class Program { static void Send(NamedPipeClientStream client, Message data) { StreamString ss = new StreamString(client); var messageString = new JavaScriptSerializer().Serialize(data); Console.WriteLine("Send message: " + messageString); ss.WriteString(messageString); } static Message Receive(NamedPipeClientStream client) { StreamString ss = new StreamString(client); string messageString = ss.ReadString(); Console.WriteLine("Receive message: " + messageString); return new JavaScriptSerializer().Deserialize<Message>(messageString); } static void Main(string[] args) { string filePath = "SomeFile.xml"; var client = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut); try { client.Connect(); var message = new Message(); message.FilePath = filePath; Send(client, message); var response = Receive(client); var data = int.Parse(response.Data); data = data + 100; message = new Message(); message.FilePath = filePath; message.Data = data.ToString(); Send(client, message); } finally { client.Close(); } } }
StreamString:
Die Klasse kannst du von der folgenden MSDN Seite kopieren: https://msdn.microsoft.com/de-de/library/bb546085%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
-------
Welcher Ansatz für dich am Besten passt kann ich natürlich nur schwer sagen, da ich nicht genau weiß was das Ziel des ganzen ist.
Ganz nebenbei: Das XML in deinem ersten Post hat kein valides Format. Um den Client und Server Code aus diesem Post zu verwenden muss das Format natürlich valide sein, da Standard XML Klassen verwendet werden.
Quellenangaben:
Teile des Codes und die Art der Interprozess Kommunikation sind vom Beispiel auf der folgenden MSDN Seite kopiert: https://msdn.microsoft.com/de-de/library/bb546085%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
Gruß,
David
- Bearbeitet David Roller Mittwoch, 30. November 2016 21:45 Typo
- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Montag, 5. Dezember 2016 09:12
- Als Antwort markiert Martin Scheid Montag, 5. Dezember 2016 18:34
-
Hi Martin,
nur um es erwähnt zu haben :)
Natürlich sind bei den Code Beispielen von mir, die ich hier poste, sehr vereinfacht.
Bei den Post oben werden etliche mögliche Fehlquellen wie z.B. null-pointer checks, exceptions, ... einfach ignoriert.
Interprozess Kommunikation ist kein leichtes Thema und kleine Fehler können schon zu komplizierten Deadlocks und / oder Race Conditions führen.
Das heißt um den Code dann wirklich produktiv einsetzen zu können ist noch "etwas" Arbeit nötig :)
Deswegen ist auch die Methode mit dem Globalen Mutex von oben bei weitem die einfachere Variante.
Gruß,
David
- Bearbeitet David Roller Mittwoch, 30. November 2016 21:44 Typo