Laden...
T
T-Virus myCSharp.de - Experte
Entwickler noobie :D Nordhausen, Nörten-Hardenberg Dabei seit 17.04.2008 2.224 Beiträge
Benutzerbeschreibung

Forenbeiträge von T-Virus Ingesamt 2.224 Beiträge

14.06.2022 - 08:32 Uhr

Auch mit VS hat es nichts zu tun.
Es liegt einfach an json selbst.
Und json für die Configs ist zum einen flxibler und auch kompakter als die alten XML Configs.
Gerade wenn man schon seit .NET 2.0 dabei ist, merkt man was für Welten dazwischen liegen.
Ich muss hier teilweise noch mit mehreren KB großen XML Configs mit Meterlangen AssemblyRedirects arbeiten.
Deshalb fährst du mit json um eingies besser.

Ansonsten muss man halt die Unterschiede einmal kennen lernen, dann ist es zukünftig kein Problem.
Da json auch im .NET Umfeld seit Jahren etabliert ist, sollte sich dies auch für dich nicht als schwer darstellen.

T-Virus

06.06.2022 - 11:58 Uhr

Dann passt es ja 🙂

T-Virus

05.06.2022 - 12:47 Uhr

@Gimmick
Wäre auch möglich aber man müsste einiges mehr an Prüfungen durchführen.
Man muss z.B. beachten, dass auf allen Ebenen des Pfad Teile fehlen können.
Also z.B. eine Zoomstufe am Anfang (0), Ende (21) oder mitten (1-20) drin.
Das gleiche gilt für X Ordner und die Y Dateien.

Entsprechend müsstest du dir die aktuelle Zoomstufe merken.
Abhängig davon musst du die unterschiedliche X/Y Mengen beachten, da jede Zoomstufe ihre eigene Menge an X/Y Kombinationen hat.

Zusätzlich könnte man den HashSet Ansatz noch beschleunigen, wenn man die Prüfungen auf mehrere Kerne verteilt.
Hier könnte man z.B. pro Zoomstufe mit Parallel.For die Daten gegenprüfen.
Da X/Y pro Zoomstufe in der gleichen Anzahl vorliegen müssten, könnte man damit noch die Abfragen beschleunigen.
Bei größeren Prüfungen wie z.B. bei gößeren Ländern wie Deutschland etc. kann man noch einige Sekunden einsparen.

T-Virus

02.06.2022 - 10:32 Uhr

Contains bei einer Liste ist halt langsam, weil er alle Elemente durchgehen muss um zu schauen ob es einen Treffer gibt.
Dadurch hast du wieder eine lineare Suchdauer, die abhängig von der Anzahl der Elemente und der Position des gesuchten Elements ist.
Im schlimmsten Fall muss er bei Lücken dann alle Einträge durchlaufen um keinen Treffer zu ermitteln.

HashSet sowie Dictionary lösen dies, da beim HashSet der Eintrag und beim Dictioanry der Key über einen ermittelten HashCode (int) via GetHashCode berechnet werden.
Dieser wird dann als Suchposition intern verwendet, was eine Suche extrem beschleunigt.

T-Virus

02.06.2022 - 09:44 Uhr

Im ersten Schritt solltest du das zusammensetzen des Pfad über Stringgebastel durch Path.Combine ersetzen.
Dadurch sparst du viele unnötige String Objekte, die jetzt im Speicher liegen bzw. aufwändig durch GCs entfernt werden müssen.

Ich würde auch folgenden Ansatz versuchen.

  1. HashSet für Koordinaten anlegen (String Aufbau Zoom|X|Y)
  2. HashSet mit allen vorhandenen Dateien befüllen
  3. Durch die Schleife durchlaufen, Keys bilden und prüfen ob vorhanden
  4. Wenn HashSet.Contains = false, dann hast du eine Lücke

Damit dürftest du noch etwas schneller sein und sehr viele unnötige String Objekte sparen 🙂
Anbei kannst du beim bilden des Key auch String Interpolation verwenden.
Dadurch hast du nur ein Objekt mehr am Ende.


HashSet<string> existingFiles = new HashSet<string>();

// HashSet mit vorhandnene Dateien befüllen
string[] files = Dicrectory.GetFiles(dir, "*.png", SearchOption.AllDirectories);

foreach(string file in files)
{
    // Pfad zerlegen um Zoom, X, Y zu ermitteln
    string zoom = bla;
    string x = blub;
    string y = blablub;

    string key = $"{zoom}|{x}|{y}";
    existingFiles.Add(key);
}

for (int tx = point1.X - 1; tx < point2.X + 2; tx++)
{
    for (int ty = point2.Y - 1; ty < point1.Y + 2; ty++)
    {
        string key = $"{zoom}|{x}|{y}";

        if(existingFiles.Contains(key))
            tiles++;
    }
}

Nachtrag:
Wenn du die Ermittlung des HashSet in eine eigene Methode packst, kann der GC das string[] auch direkt weg hauen.
Dadurch ist dein Speicher nur auf das HashSet als größtes Objekt limitiert.
Dürfte sich aber in Grenzen halten.

T-Virus

30.05.2022 - 09:54 Uhr

Ah okay.
Dann vermute ich mal, dass du über das Dictionary schon die Dateien vorcachen willst.
Also für X/Y/Level als Key und die Datei als Value im Dictionary.

Würde ich aber nicht machen, arbeite hier lieber mit dem Dateisystem Cache und lade die Bilder wenn diese benötigt werden.
Wenn du die Bilder auf den dichtesten Zoom Level nutzt, werden schon je nach Bereich einige GB anfallen.
Diese kannst du dann kaum cachen bzw. müsstest abhängig vom vorhandenen RAM Maßnahmen ergreifen.

Das Dictionary kann bei Geräten mit zugeringem Speicher schnell zum OutOfMemoryException führen.
Ebenfalls müsstest du dann selbst die Speicherverwaltung übernehmen z.B. beim Wechsel des Zoom Levels alle Eintärge für nicht passende Level wieder entfernen.
Und du musst fehlende Einträge, für die es auch lokal keine Datei gibt, dann mit einem Dummy Platzhalter liefern.

Im einfachsten Fall speicherst du die Bilder lokal wie auf dem Webserver und kannst den Pfad dann direkt bilden und abrufen.
Damit fährst du vermutlich am besten.

T-Virus

29.05.2022 - 21:45 Uhr

Gibt es dafür nicht fertige Lösungen von bzw. für OpenStreetMap?
Ich meine mich darin zu erinnern, dass wir was ähnliches bei uns verwenden, wenn auch nicht offline.
Wir rendern z.B. auch die OpenStreetMap Karte von einem eigenen Mapnik Server bei uns.
Wir lassen diese aber erst rendern, wenn diese benötigt werden und cachen diese dann über den Server.
Da wir die Daten auch ca. einmal im Monat updaten lassen, müssen diese auch neu gerendert werden.
Damit dürftest du auch am besten fahren.

Das gesamte Material Offline zu speichern ist wegen der Masse kaum möglich.
Bei uns liegen ca. 800+ GB gerenderte Bilder rum.
Auch andere Dienste bieten dann nur einen Teilbereich der Daten offline an.

Nachtrag:
Wie kopiert ihr den die Daten auf das NAS?
Nutzt hier hier z.B. robocopy?
Dort könnt ihr auch mit Threads arbeiten, was die Performance u.U. noch mal steigert.
Nutze ich auch bei vielen kleinen Dateien.

T-Virus

29.05.2022 - 20:06 Uhr

Das sind aber zwei Paar Schuhe.
Der Explorer ist leider nicht gerade performant bei vielen Dateien und spielt hier erstmal keine Rolle.

Die .NET Lösung, ist wie Abt schon zu Recht sagt, auch nicht die performanteste Lösung, da hier sehr viele Rechteprüfungen etc. durchlaufen werden müssen.
Auch triviale Dinge wie das durchlaufen von großen Verzeichnis Strukturen können dann langsamer sein als Zugriffe über native System APIs wie die WinAPI.
Dadurch hat man aber wieder native Abhängigkeiten, die man eigentlich vermeiden möchte.

Mich würde aber interessieren ob sich hier zwischen .NET Framework und dem neueren .NET 5/6 schon was getan hat.
Oder ist hier ggf. zukünftig was geplant?

T-Virus

27.05.2022 - 09:31 Uhr

@BerndFfm
Du könntest auch mit EnumerateFiles arbeiten.
Damit musst du nicht alle Dateinamen bzw. Pfade im Speicher halten.
Wenn du auch nur einen Teil der Namen brauchst, kannst du damit die Nummer aus dem Namen auslesen und diese in ein HashSet packen.

Nachtrag:
Doku:
Directory.EnumerateFiles Methode (System.IO)

T-Virus

20.05.2022 - 19:00 Uhr

Wieviele Einträge hast du den und wie oft musst du nach Einträgen suchen?
Alternativ kannst du, wenn es nur um einzelne Attribute geht, diese auch in unterschiedliche Dictionaries packen.

Z.B. nutze ich auch eine eigene Klasse, die meine Einträge je nach Kriterium in eigene Dictionary packt.
Dadurch kann ich die Treffer direkt ermitteln.
Wenn du Attribute aber kombinieren musst, wird dieser Ansatz vermutlich nicht funktionieren.
Dann müsstest du auch sicherstellen, dass neue Einträe überall eingefügt werden.

T-Virus

20.05.2022 - 18:19 Uhr

Ja, bei List<T> werden alle Einträe geprüft und beim ersten Treffer direkt das Ergebnis geliefert.
Wenn du nur eindeutige Einträge hättest, dann könntest du auch Dictionary<TKey, TValue> nehmen.
Dürfte vermutlich aber nicht dein Anwendungsfall sein.

Anbei die Doku zu List<T>:
List<T> Klasse (System.Collections.Generic)

T-Virus

19.05.2022 - 13:03 Uhr

Dein Problem sollte sich doch direkt über den ResourceManager lösen lassen.
Dort kannst du doch einfach bei GetString die CultureInfo für die Sprache mitgeben.
Dann hast du die richtige Übersetzung für die ausgewählte Sprache.
Du benötigst dann nur in deiner UI einfach die resx Datei für die Form mit der jeweiligen Sprache.
Zusätzlich sollte man auch eine neutrale Sprache als Default mitbringen als Fallback falls Übersetzungen fehlen.

Die Formatierung für die Textbox kannst du dann auch über die ausgewählte Sprache formatieren, was du selbst ja schon machst wenn auch über Umwege mit deiner Lib.
Damit kannst du ohne Probleme mehrere Sprachen anzeigen.
Passend dazu schau dir den Jetbrains Link von Abts zweiten Beitrag und die Doku zum ResourceManager an.
Dann solltest du es hinbekommen ohne deine Lib oder eine extra kompilierte DLL einbinden zu müssen.
Die Resourcen werden dann direkt in die Form DLL einkompiliert.

T-Virus

18.05.2022 - 09:42 Uhr

So ganz klar sind mir die Vorteile leider auch nicht.
Nach dem Überblicken des Projekts scheinen die Übersetzungen bei dir halt auch wieder fix in den Code gepackt zu werden.
Oder gibt es in deiner Lib auch die Möglichkeit, die Übersetzungen aus den bestehenden resx Dateien zu nehmen?
Falls nicht, wäre es wieder ein Schritt zurück da man Übersetzungen nicht direkt in den Code packen will und vorhandene Übersetzungen auch weiterverwenden will.
Gerade dies wäre ein wichtiger Punkt mit dem man sich befassen müsste.

Für Projekte, die den .NET Weg bereits nutzen, sehe ich auch keinen Vorteil.
Die Typsicherheit spielt dabei auch nur eine Untergeordnete Rolle.
Diese kann man auch durch Kapselung der .NET Methoden z.B. durch Extention Methods erreichen.
Dafür brauche ich dann keine Lib.

Mir fehlen halt auch gute Beispiele wo ich nun Vorteile bei der Nutzung deiner Lib gegen den .NET Weg habe.
Vielleicht solltest du hier dein Beispielprojekt erweitern um dies etwas klarer hervorzustechen.

T-Virus

10.05.2022 - 17:18 Uhr

Liegt daran, dass bei WriteAllLines ein String Array erwartet wird.
Hier muss eher WriteAllText verwendet werden.

T-Virus

10.05.2022 - 12:34 Uhr

Okay, aber einiges im Code macht keinen Sinn.
Die Prüfungen mit Contains, kannst du bei vorheriger Konvertierung einfach über eine Werte Prüfung lösen.
Ebenfalls scheinst du auch in den Schleifen mehrfach unnötig TryPase aufzurufen.
Je nachdem wieviele Zeilen du hast, verheizt du dadurch unnötig Zeit um die immer gleichen Spalten zu konvertieren.

Es wäre vermutlich auch hilfreicher, wenn du einmalig die Zeile aus den zeilen Array ausliest und zwischen speicherst.
Aktuell musst du immer wieder über zeilen[x1] darauf zugreifen, was du auch mit einer string Variable vereinfachen kannst.
Auch ist mir nicht ganz klar war zeilen2 ist bzw. woher es kommt.

Mit den if Abfragen mit dem break der inneren Schleife hast du auch einie magic numbers.
Mach daraus am besten Konstanten damit später klar ist, warum du darauf prüfst und rausspringen musst.

Die Meldungen mit fehlerhaften Zeilen würde ich einmal sammeln und dann insgesamt ausgeben.
Sonst musst du für jede fehlerhafte Zeile dem Benutzer ein Fenster anzeigen.
Das macht bei vielen fehlerhaften Zeilen keinen Spaß!

T-Virus

10.05.2022 - 12:21 Uhr

Wenn in den Spalten nur Zahlenwerte stehen können, dann kannst du auch einfach den Inhalt per Int32.TryParse versuchen umzuwandeln.
Dabei sollte aber geprüft werden ob der Content nicht leer ist, sonst knallt es bei TryParse.
Dann musst du auch nicht auf 2 oder 3 Stellen prüfen 😉

Anbei wäre es auch besser, denn du deinen Code sauberer aufteilst.
Aktuell scheint die gesamte Verarbeitung in einer Methode zu sein, was das lesen des Code unnötig schwer macht.
Das auslesen, verarbeiten und schreiben sollte in eigene Methoden ausgelagert werden.
Im einfachsten Fall lagerst du diese in eine Klasse aus, die sich dann darum kümmert.
Dann kannst du den Code auch später z.B. mit Tests (Unittests) abdecken.

T-Virus

09.05.2022 - 17:45 Uhr

Geht es den um die Firewall?
Ich gehe eher davon aus, dass es um Ausnahmen von Anwendungen von der Überwachung geht nicht aber um die Firewall Regeln.
Aber ohne Details was der TE will, sind dies nur Annahmen.

T-Virus

09.05.2022 - 17:17 Uhr

Es gibt keine allgemeine API für sowas, dass musst du je nach Antiviren Lösung bei dem jeweiligen Hersteller anfragen.
Dabei geht auch jeder seinen eigenen Weg.

Und i.d.R. bieten diese für normale Endanwenderlösungen keine APIs für sowas, dies ist dann den Business/Enterprise Lösungen vorenthalten.
Kannst du aber mit dem jeweiligen Hersteller klären.

Nachtrag:
Wäre auch übrigens ein gutes Einfallstor für Viren/Trojaner wenn es eine allgemeine Lösung per API gibt.
Was genau willst du den damit machen?

T-Virus

09.05.2022 - 09:23 Uhr

Zusätzlich dazu, kannst du auch Redis einbinden.
Wenn du nur einen Prozess hast, kannst du die Daten einfach lokal vorhalten und in Redis speichern/updaten.
Damit könntest du nahe zu endlose Datenmengen wegspeichern.
Durch Pub/Sub kannst du dann auch bei verteilten Anwendungen die Caches updaten lassen.

T-Virus

09.05.2022 - 09:09 Uhr

@Christoph K.
Welches reale Problem wäre dies den, wenn ich fragen darf.
Sieht dein Code im produktiv System genauso aus, dann kann es nicht funktionieren.
Wäre es hier nicht sinnvoll nur benötigte Daten direkt im Cache abzulegen anstatt Unmengen an Einträgen zu generieren?
Dies wäre für sich gegeben schon ein Dictionary mit eindeutigen Keys.

Einträge sollten nur abgelegt/eingefügt werden, wenn diese benötigt werden sonst läufst du eben auf das Speicherproblem.
Ggf. wäre auch die Einbindung von Redis als Cacheserver sinnvoll um nahezu endlose Daten zu speichern.
Nutzen wir auch um größere verteilte Caches zu nutzen.

T-Virus

09.05.2022 - 09:05 Uhr

Wie genau soll diese Prüfung aussehen?
Wenn du keine Schnittstelle hast um die Firewall abzufragen, dann dürfte es nicht ohne weiteres klappen.
Die Firewall selbst gibt keine Informationen preis welche Einstellungen gesetzt sind.
Wäre fatal, wenn eine Firewall so geschwätzig wäre und solche Daten einfach an jeden Client senden würde.

T-Virus

07.05.2022 - 11:26 Uhr

@mpmic
Nein, genau anders herum.
Du gibst MySetup einfach über den Konstruktor an WDSettings mit.


// Übergabe über den Konstruktor
WDSettings wDSettings = new WDSettings(MySetup);

// Konstruktor
 public WDSettings(Setup setup)
{
    InitializeComponent();
    CurSetup = setup;
    Backup = CurSetup;
    PathfromBackup();
}

T-Virus

07.05.2022 - 11:01 Uhr

Das liegt daran, dass du MySetup erst nach dem Aufruf des Konstruktor von WDSettings übergibst.
Da du aber im Konstruktor von WDSettings dann CurSetup, was hier noch null ist, dann in Backup speicherst und dann damit arbeiten willst, knallt es.
Du solltest dich erstmal mit den Grundlagen von OOP beschäftigen.
Gerade mit WPF hast du auch einen technischen Ansatz, den du aktuell nicht richtig umsetzt.
Dort arbeitet man nicht mit Code Behind sondern nach dem MVC/MVVM Muster.

Dadurch sind deine aktuellen Prüfungen auf Änderungen nicht nötig, da das Muster Änderungen an das Model selbst melden würde.
Dazu müsstest du aber erstmal die Grundlagen inne haben, damit du das sauber umsetzen kannst!

Nachtrag:
Im einfachsten Fall kanst du das Problem lösen in dem du MySetup an den Konsturktor mitgibst oder deine Verarbeitung nach dem setzen von CurSetup dann in einer public Methode duchführst.

T-Virus

06.05.2022 - 11:38 Uhr

Meine Frage wäre auch welchen Sinn dieser Code hat.
Du hast hier eine while(true) Schleife was so oder so zu einem endlosen Durchlauf führt und früher oder später zu einem Überlauf oder OutOfMemory Exception.
Etwas mehr Context zu deinem Vorhanden könnte ggf. auch zu einer sinnvolleren Lösung führen.

T-Virus

05.05.2022 - 16:46 Uhr

Auf den ersten Blick, weil du den StreamWriter nicht per Close schließt.
Dadurch werden noch nicht geschriebene Daten nicht aus dem internen Puffer geschrieben.
Close schreibt die Daten raus und schließt dann auch sauber die Datei.

Schau dir dazu am besten die Doku zu StreamWriter nochmal an und zusätzlich auch Dispose.

T-Virus

28.04.2022 - 11:41 Uhr

Die Meldung klingt danach, dass du die StartInfo zwar füllst aber das Programm nicht startest.
Dadurch knallt es auch, da du einen Stream lesen willst, der gar nicht geöffnet werden kann, da das Programm nicht läuft.

Doku:
https://docs.microsoft.com/de-de/dotnet/api/system.diagnostics.processstartinfo?view=net-6.0
https://docs.microsoft.com/de-de/dotnet/api/system.diagnostics.process?view=net-6.0

T-Virus

27.04.2022 - 22:01 Uhr

Klingt nach einem Münzwurf was die Eindeutigkeit der Dateien angeht, wenn du nur 200 Bytes mitten in der Datei lesen willst.
Du kannst zwar eine gewisse Eindeutigkeit durch Hashing bei Dateien ermitteln, dazu müsstest du aber die ganze Datei einlesen und hashen.
Dateien haben an und für sich auch keine eindeutigen IDs.

Mir ist aber nicht klar, wie du darauf kommst, dass eine mp4 Datei auf Platform A anders sein könnte als auf Platform B.
Auf beiden hast du im Endeffekt die gleichen Bytes.
MP4 und co. sind spezifierte Formate mit einem fixen Aufbau.

Ein für alle Platformen eindeutige ID erzeugen klappt m.W. nur durch Hashing.
Eine original und eine geänderte Datei, z.B. durch Schnitt oder andere Änderungen in Bild/Ton, haben dann aber auch unterschiedliche Hashes/Bytes.
Wenn du solche Dinge vergleichen willst, wird es schon etwas komplexer und dürfte den Rahmen deines Vorhabens ggf. sprengen.
Dann müsstest du nicht nur stumpf die Bytes auswerten sondern müsstest direkt Bild/Ton z.B. mit Tools auswerten.

T-Virus

24.04.2022 - 18:54 Uhr

@Palladin
Hab ich oben bereits angepasst, war in der ersten Version noch drin.
Hab in den Source von .NET 6 und 4.8 geschaut.
In .NET 6 wird tatsächlich die nested Class geliefert.
Dort ist SHA256Managed nur auch als Obsolete markiert.
In .NET 4.8 wird noch etwas interne Magic durchgeführt bzw. über Magic Strings dann eine Instanz von SHA256Managed geliefert.

.NET 6 Implementierung
.NET 4.8 Implementierung

T-Virus

24.04.2022 - 18:27 Uhr

Die Create Methode liefert eine Instanz der SHA256 Implementierung.
Du arbeitest dann gegen die Abstrakte Klassen SHA256 Instanz.
Der Konstaruktor ist auch als protected markiert, da durch kannst du auch keine direkte Instanz von SHA256 erzeugen.
In der Doku zu SHA256Managed wird auch darauf hingewiesen, über Create von Base Type (SHA256) nutzen um eine Instanz zu erhalten.

Doku:
SHA256 Klasse (System.Security.Cryptography)

T-Virus

22.04.2022 - 15:55 Uhr

Mein Vorschlag war es eigentlich, dass die UI Anwendung einfach eine Konsolenanwendungen per Porcess.Start startest.
In dieser Konsolenanwendung ist dann die eigentliche Self Hosted ASP .NET Anwendungen.
Damit wäre deine UI und die ASP .NET Anwendung entkoppelt.

Ansonsten wirst du auch nicht drum herum kommen, dass ganze zu entkoppeln.
Ob MAUI UI hier für MAC der beste Ansatz ist, kann ich nicht magels MAC und Erfahrung mit MAUI UI nicht sagen.
Du kansnt es ja im einfachsten Fall mit einem Testprojekt mal durchspielen.

T-Virus

22.04.2022 - 15:14 Uhr

Warum nicht die ASP .NET Lösung komplett von UI Anwendungen nicht entkoppeln?
Am einfachsten wäre es vermutlich, die ASP .NET Anwendung als Konsolenanwendung laufen zu lassen.
Dann musst du diese in anderen UI Anwendungen einfach al seperates Programm starten.

Ansonsten wäre aber die Frage, warum die ASP .NET Anwendung nicht als eigenes Web laufen soll.
Gibt es einen bestimmten Grund für diese Bindung an deine WinForms Anwendung?

T-Virus

12.04.2022 - 11:43 Uhr

@Palladin007
Der Hinweis mit der Auswahl ging mir darum, dass je nachdem was er ausgewählt hat auch noch das Framework beim Endanwender benötigt.
Aber ist natürlich richtig, sollte man nur noch nehmen wenn nötig uns sonst aust .NET 5+ setzen!

T-Virus

12.04.2022 - 11:33 Uhr

Die .exe allein reicht auch nicht, wenn du Abhängigkeiten zu anderen Libs (DLLs) hast.
Du musst auch alles aus dem Release Ordner bereitstellen.

Ebenfalls hat .NET mit .NET Core und später .NET 5 auch einen großen Umbruch durchlebt.
Das alte Framework wird nicht mehr weiterentwickelt, jetzt gibt es .NET Core/5+ als kompaktere Laufzeitumgebung.
Dort kannst du aber auch die Anwendungen "statisch" kompilieren, damit keine extra Laufzeit installiert werden muss.
Hier müsstest du schauen welche Konsolenanwendung du hast.
Du kannst bei den Projekten in VS 2019 schon zwischen .NET Framework und .NET Code/5 Konsolenanwendungen auswählen.
Steht dann auch in den Projekt Eigenschaften.

T-Virus

09.04.2022 - 09:03 Uhr

Du solltest dir nochmal anschauen, wie Tasks und async/await funktionieren.
Deine benötigte Lösung ist banal einfach, wenn man du verstehst, wie du async/await und Tasks verwenden musst!
Du bekommst von deiner Methode den Task<Person> zurück.
Durch das await, wird auf den Task gewartet und dir direkt Person geliefert.
Dadurch kannst du direkt auf den Vorname zugreifen.


Person person = await App.Database.GetVornameAsync(200);
_ = DisplayAlert("Info", person.Vorname, "OK");

Nachtrag:
Du solltest die Methode nicht GetVornameAsync nennen, da du keinen Vornamen sondern die ganze Person lieferst.
Am besten nennst du die Methode allgemeiner wie z.B. LoadPerson!

Nachtrag 2:
Du solltest dann aber auch darauf achten, dass Person bei ungültigen IDs null sein kann.

Nachtrag 3:
FZelle war schneller 🙁

T-Virus

07.04.2022 - 20:34 Uhr

Kleiner Hinweis am Rande.
Als Anwendungsdatenbank nimmt man unter .NET nicht Access.
Dafür ist es nicht gedacht und sollte in .NET auch nicht verwendet werden, wenn es keinen driftigen Grund gibt.
Dafür gibt es Embedded Datenbanken wie SQLite.

Diese werden auch von aktuellen OR Mappern wie Entity Framework Core unterstützt und nehmen dir hier den SQL bau sogar komplett ab.
Solltest du dir mal anschauen, spart dir bei großen Projekten enorm viel Tipp arbeit.

T-Virus

04.04.2022 - 21:35 Uhr

Ist den sichergestellt, dass Program.protokollieren true ist?
Falls nicht, wird der ganze Block übersprungen, dann kann auch nichts geloggt werden.
Solltest du im einfachsten Fall per debugger prüfen können.

Du hast aber mit dem BinaryWriter noch ein anderes Problem.
Du öffnest die Datei mit FileMode.Create, was dazu führt, dass die Datei bei vorhanden sein an Position 0 also am Anfang geöffnet wird.

Damit schreibst du aktuell den Header immer an den Anfang der Datei.
Wenn du dies mit den späteren Logdaten genau so machst, dann würdest du alle Daten immer wieder an den Anfang der Datei schreiben.
Die Datei muss dann mit Append geöffnet werden.
Dann werden weitere Einträge an das Ende der Datei geschrieben.
Nur sollte dann der Header vermutlich nur einmalig geschrieben werden.
Musst du dann in deinem Programm anpassen.

T-Virus

04.04.2022 - 21:05 Uhr

Mir ist nicht klar wie du dort die Daten zwischen den Programmen hin und her schiebst.
Im einfachsten Fall kannst du die Daten z.B. als Parameter String (Argument) an das Programm übergeben.
Die Ausgabe des Programms kannst du dann als Rückgabe verwenden.

Oder soll das zweite Programm dauerhaft laufen als z.B. Worker Prozess?
Kann dein erstes Programm die Daten nicht selbst verarbeiten?
Dann kannst du dir den Umweg sparen.

Ansonsten würde ich schauen, dass du z.B. über einen Selfhosted WCF Service die Daten an das Programm schickst und dann auf die Antwort wartest.
Alternativ kannst du auch asynchron die Verarbeitung durchlaufen.

Anbei sagt der Titel deines Threads vermutlich kaum jemanden etwas.
Hier solltest du genauer erklären mit welchen Techniken du arbeitest und wo es klemmt.

Nachtrag:
Hab gerade in die Doku geschaut aber mir ist nicht ganz klar wie du dort mit NamedPipes arbeitest.
Laut der Doku gibt es hier NamedPipeServerStream und NamedPipedClientStream.
Dort kannst du eingetlich ganz einfach mit StreamReader/StreamWriter auch Zeilenbasiert arbeiten

Doku:
NamedPipeClientStream.Connect Method (System.IO.Pipes)
https://docs.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeserverstream.waitforconnection?view=netframework-4.8

Hab zwar selbst noch nicht damit gearbeitet, dürfte dann aber die einfachste Lösung sein.

Nachtrag 2:
Anstelle des uralten IAsyncResult solltest du dir async/await anschauen.
Das alte Muster ist noch aus vor .NET 4.0 Zeiten bevor es Tasks gab.
Das sollte man heute nicht mehr verwenden bzw. nur noch wenn es nötig ist.
Aus heutiger Sicht ist das Muster veraltet und durch async/await einfacher gelöst.

T-Virus

19.03.2022 - 19:47 Uhr

Nimms mir bitte nicht übel aber der Code ist alles andere als sauber.
Gerade dein Umgang mit den Threads und Stopwatches ist aus weder sinnvoll noch der richtige Ansatz.
Schau dir dazu am besten mal async/await mit Tasks an.

Threads sollte man selbst nicht mehr Instanzieren bzw. nur noch wenn dies absolut nötig ist.
Durch Tasks lässt sich dein Problem sauber lösen.

Ansonsten ist mir der Zweck der ganzen Thread.Sleep Schleifen nicht klar.
Wenn du 300 ms warten willst, dann gib auch 300 an Thread.Sleep.
Dort 300x Thread.Sleep aufrufen, verlängert nur deine Wartezeit, dadurch wird diese also nur noch länger und ungenauer.
Zielführen wäre es hier eher auf eine asynchrone Verarbeitung zu warten.
Aber dafür brauchst du dann Tasks mit async/await.

T-Virus

19.03.2022 - 19:42 Uhr

Und anstelle von DataTable/DataSet solltest du eigene Datenstrukturen (Klassen) verwenden.
DataTable/DataSet sind schon speichertechnisch Brocken, die enorm vie Speicher verbrauchen!
Wann immer möglich verzichte darauf, nuzte diese nur wenn es absolut nötig ist.

Ansonsten klingt dein aktueller Ansatz ziemlich nach Magic Code und weniger nach einer Schnittstelle zwischen Client und Server.
Hier sollte dein Server fertige Schnittstellen anbieten um die Daten, die du benötigst, zu liefern.
Entweder über eine Api oder ein fertiges Protokoll.
Hier würde ich beim Server z.B. auf eine Http Api wie Web Api von Microsoft setzen.
Dann kann dein Client einfach per Http Abfragen die Daten abholen und durch Serialisierung sowohl den Request/Response dann als Json hin und her schieben.
Damit hast du schon eine recht gute Grundlage und kansnt durch die Api auch saubere Schnittstellen defineiren.

T-Virus

12.03.2022 - 10:40 Uhr

Kurze Suche zeigt mir eigentlich, dass ImageBrush hier die falsche Klasse ist.
In WPF gibt schon ein Image Control, was du eher verwenden willst.

Link:
WPF - Image

Nachtrag:
Hier auch die Doku dazu.

Doku WPF Bilder

T-Virus

11.03.2022 - 12:39 Uhr

Und genau dafür hat man den Code nicht nur lokal auf der Platte sondern in einem Repository.
Dann kann man einfach den Stand wiederherstellen und fertig.
Wenn du keine Sicherung von deinem Stand hast, wirst du alles händisch wieder herstellen müssen.
VS kann nur begrenzt bei solchen Fehlern helfen, vorallem bei einem Neustart ist dann i.d.R. keine Möglichkeit mehr da um den alten Stand wiederherzustellen.

Zukünftig solltest du deinen Code mindestens in einem Git Repository lokal speichern.
Oder noch besser, setzt dir einen Server dafür auf, der regelmäßig Sicherungen macht!

T-Virus

10.03.2022 - 19:27 Uhr

Wenn du schon weiß welche Tankstelle du brauchst, kannst du per Linq oder direkt über Find diese in der Liste abfragen.


var result = JsonConvert.DeserializeObject<List<Spritpreisrechnerat>>(json);
var tankstelle = result.Find(r => r.Name == "Diskont Tankstelle");

var allepreise = tankstelle.Prices;
var tankstelle = tankstelle.Name;
var adresse = tankstelle.Location.Address;

foreach (var preis in allepreise)
{
    Console.WriteLine(tankstelle + " : " + adresse + " : " + preis.Amount);
}

T-Virus

10.03.2022 - 12:03 Uhr

@Abt
Wusste nicht, dass es das gibt.
Macht die Umsetzung dann natürlich einfacher.

Der hinweis mit C/C++ bezieht sich ja extra auf ein Echtzeit OS.
Klar, dass es ohne passendes System auch nicht Echtzeit ist 🙂

T-Virus

10.03.2022 - 11:52 Uhr

Neben dem OS spielt hier auch die Software eine Rolle.
.NET ist keine Echtzeit Laufzeitumgebung bzw. ist dies nicht die primäre Zielgruppe für die Platform.

Für solche Verarbeitungen braucht man eher Systemnahe Programmiersprachen wie C/C++ die dann auch auf einem Echtzeitsystem die Abläufe zeitlich garantieren können.
Je nachdem was du hier machst, könntest du mit einem Linux mit Echtzeit Kernel und mit einem entsprechenden C/C++ Programm oder ggf. schon mit einem fertigen Tool dein Problem lösen.

T-Virus

08.03.2022 - 10:01 Uhr

Du musst hier wegen der unterschiedlichen Typen die Bytes noch zu int casten.
Im einfachsten Fall kannst du einfach mit einer foreach Schleife die Bytes durchgehen und einfügen.


ConcurrentQueue<int> coll = new ConcurrentQueue<int>();

forech(byte b in bytes)
{
    coll.Enqueue((int)b);
}

Doku:
ConcurrentQueue<T> Klasse (System.Collections.Concurrent)

T-Virus

06.03.2022 - 10:42 Uhr

@Th69
Hab ich tatsächlich falsch verstanden 🙁
Soweit ich das aber sehe läuft für die .NET 4 Version der Support am Jahresende aus.
Scheint also auch nicht mehr von MS weiterentwickelt und supportet zu werden.
Dürfte in dem Fall für eine rein interne Lösung aber kein großes Problem sein.
Letzte Version für .NET 4.0 ist auch vom Mai 2021 also noch recht aktuell.

T-Virus

05.03.2022 - 18:36 Uhr

@Sneco
Mit SAP Connector meine ich ein Programm, was über ERPConnect mit SAP kommuniziert.
Sowohl zum Daten abrufen sowie mit senden von Daten via Funktionsbausteinen.
Schau die ERPConnect an, dass ist genau das was du brauchst.
In der Doku findest du auch alle nötigen Anleitungen und was du machen musst um die Verweise im Projekt zu hinterlegen.

Den SAP Connector für .NET 3.0 kannst du vergessen, der ist uralt!
.NET 3.0 ist auch bereits tot bzw. unspportet, damit braucht man heute nichts mehr machen.

T-Virus

05.03.2022 - 09:31 Uhr

Anbei würde ich dir auch empfehlen sich mal den UdpClient aus .NET anzuschauen.
Dort wird der Socket für die Udp Verbindung gekapselt und nimmt dir damit einiges an Arbeit ab.
Ist auch vom Code her etwas kompakter und sauberer als dein jetziger Ansatz.

Link:
UdpClient .NET

Nachtrag:
Die Begin/EndReceiveFrom Methoden sind noch das Asynchrone Programmierungsmuster aus .NET 2.0 Zeiten.
Dies wird zwar noch supportet, ist aber technisch outdatet.

Hier solltest du dir zukünft Tasks mit async/await anschauen.
Dann kannst du die *Async Methoden von UdpClient/Socket verwenden.
Damit würde sich auch der Zugriff auf die Controls sauber lösen lassen.

T-Virus

05.03.2022 - 09:26 Uhr

Dein aktueller Ansatz kann ja auch nicht funktionieren.
Die Anwendung schließt beim beenden der Anwendung auch die Verbindungen, so kannst du also nicht damit arbeiten.
Du solltest hier, wie M.L. schreibt, dir die entsprechende Lib installieren und einbinden.
Nur so kannst du sauber mit C# auf SAP zugreifen.

Dafür brauchst du lokal auch kein SAP.
Du brauchst zum entwickeln nur die .NET Libs und Referenzen.
Ich entwickle selbst gerade an einem SAP Connector auf Basis von ERPConnect.
Damit hast du dann alles um mit SAP in C# zu arbeiten.

T-Virus

01.03.2022 - 16:20 Uhr

Kannst du in deinem Profil unten Rechts.
Dort steht auch "Beiträge des Benutzers".

T-Virus