Beim Start die Listen im Hintergrund schon mal laden...

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    Beim Start die Listen im Hintergrund schon mal laden...

    Hallo alle,

    ich wollte mich erkundigen, ob es irgend wie möglich ist, beim Start die Listen bzw. Observablecollection neben bei im Hintergrund zu laden? Dauert halt bis es aus der Datenbank geladen ist, daher frage ich.

    Danke im Voraus.
    hab gestern das hier ausprobiert, er kam nicht zum ende...

    C#-Quellcode

    1. ​ await Task.Run( () => {
    2. // Just loop.
    3. int ctr = 0;
    4. for (ctr = 0; ctr <= 1000000; ctr++)
    5. {}
    6. Console.WriteLine("Finished {0} loop iterations",
    7. ctr);
    8. } );


    hab es hiervon: learn.microsoft.com/de-de/dotn…g.tasks.task?view=net-7.0

    selbstverständlich hab ich den Inhalt ausgetauscht...

    EugenIS schrieb:

    (...) selbstverständlich hab ich den Inhalt ausgetauscht...

    Wenn die Iteration aus dem Beispiel als Inhalt des Lambdaausdrucks normal zu Ende läuft, der eigene Inhalt – der sonst normal und nicht als Anwenungstart abgeschlossen wird – aber nicht, könnte es damit zusammenhängen, dass der Task zu früh (bevor alles richtig geladen und initialisiert worden ist) ausgeführt wird oder man in dem Lambdaausdruck etwas invoken muss, damit alles aus dem Hintergrundthread tatsächlich ordnungsgemäß ausgeführt werden kann. Für das Ausschließen des ersten Problems könnte man eine Zeitverzögerung mit einem Timer bewerkstelligen – beim Start/Load/Main ect. den vorher auf ein bestimmtes Zeitintervall (z.B. 0,2 oder 1-3 Sekunden) eingestellten Timer dann starten und im TimerTickEvent den Timer zuerst stoppen (!) und dann den Task mit der eigentlichen Nebenaufgabe anstoßen, damit er mit der Verarbeitung beginnen kann. Die TimerTick-Interruptprozedur wird vermutlich auch das Wort Async beinhalten müssen, um passend dazu das Await verwenden zu können (Public Async Sub Timer_Tick...). Das zweite mit dem Invoken muss man halt probieren und ggfs. suchen – man kann zur Not auch erstmal alles invoken, eventuell statt des Lamdaausdrucks bzw. im Lambdaausdruck selbst auf eine eigene Prozedur verweisen, wo dann alles oder nur das Passende invokt werden könnte. Für größere/aufwendigere Aufgaben würde ich persönlich den BackgroundWorker oder einen zweiten Thread bevorzugen und verwenden, bei der klassischen Threaderstellung sollte man allerdings aufpassen, dass man sich den richtigen Thread erstellt/aussucht, der dann am Ende der Anwendung nicht mit dem Hauptthread wieder vereint werden muss, damit keine Exception entsteht oder alles im Nebenthread in Rauch und Flammen aufgeht, wenn man klickt und Exit macht. Der BackgroundWorker ist in dieser Hinsicht etwas kuscheliger – wenn alles zu Ende ist, macht er auch einfach Feierabend, ohne die hinterlassene Baustelle dabei anzuzünden. Eine dritte Möglichkeit wäre natürlich auch, dass die Aufgaben im dem Task selbst, die man sich ausgedacht hat, fehlerhaft sind, vielleicht sogar so verzwickt fehlerhaft, dass man das nicht sofort erkennt und das Ding unter normalen Bedingungen ohne Probleme durchläuft.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Gregor Jasinski“ ()

    Vorab ist es immer hilfreich, seiner Frage etwas Code beizufügen.
    Sonst gilt das Prinzip der beschlagenen Glaskugel.

    Auch solltest du uns vielleicht erzählen, was genau du vor hast.

    EugenIS schrieb:

    hab gestern das hier ausprobiert, er kam nicht zum ende...

    Wenn du den Code so ausprobiert hast, ist es klar dass da nichts passiert, weil der Compiler das in aller Regel wegoptimiert.

    Hier mal ein kleines Beispiel wenn du Daten aus einer Textdatei auslesen willst:

    C#-Quellcode

    1. public class TestAsyncLoad {
    2. public TestAsyncLoad() {
    3. m_collection = new ObservableCollection<string>();
    4. }
    5. public void Init() {
    6. var factory = new TaskFactory();
    7. factory.StartNew(LoadStuffInBackground);
    8. }
    9. ObservableCollection<string> m_collection;
    10. public async Task LoadStuffInBackground() {
    11. using (var file = File.OpenRead("myfile.txt"))
    12. using (var sReader = new StreamReader(file)) {
    13. while (sReader.Peek() != -1) {
    14. m_collection.Add(await sReader.ReadLineAsync());
    15. }
    16. }
    17. }
    18. }


    Sobald du die ​Init() Methode aufrufst (synchron), wird der Task im Hintergrund gestartet.

    Die Alternative ist, dass du mit Threads arbeitest, dann musst du dich aber definitiv mit Mutexen auseinandersetzen und ggf. auch Invocations.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    @siycah ich will listen aus der Datenbank laden. Steht da doch...

    @Gregor Jasinski Teilweise hab ich Problem damit, dass die Listen etwas größer sind, und allein die Darstellung in WPF Aufbereitung eine gefühlte Ewigkeit andauert. Bei 1000 Datensätze überhaupt kein Problem. Ab 10000 wird es schon heftig, obwohl ich das DataGrid visualisiert habe sowohl die Spalten wie auch Zeilen.
    Der Schnipsel ist doch das sowas wie du brauchst. Wo ist denn das Problem nun den Code so zu ändern das anstatt aus einer Text-Datei Daten zu lesen halt aus einer Datenbank was geladen wird? Nicht Copy&Paste ready? Sry, aber die Frage musste sein. Der Grundstein zum drauf aufbauen liegt da, nutze ihn.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    Der Grundstein zum drauf aufbauen liegt da, nutze ihn.


    Und genau so war es auch gedacht. Bei so wenig Informationen und Bereitschaft, die Frage so zu stellen dass man sieht, welche Arbeiten man selber erledigt hat, bin ich auch nicht bereit, ein Beispiel ins kleinste Detail zu produzieren.

    EugenIS schrieb:

    Nee, ich hab schon mal es besser gesehen.


    Dann hättest du es dir da abgeschaut und nicht hier gefragt, oder?
    Aber bei einer so patzigen Antwort bin ich raus.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)

    EugenIS schrieb:

    (...) Bei 1000 Datensätze überhaupt kein Problem. Ab 10000 wird es schon heftig, obwohl ich das DataGrid visualisiert habe sowohl die Spalten wie auch Zeilen.

    Normalerweise vermeidet man, solche großen Datensätze auf einmal zu laden – das gilt auch für normale Dateien in den Speicher laden, um sie z.B. zu bearbeiten. Wenn ein Hexeditor Dateien bis 10 Megabyte öffnet, wird es in der Regel ohne Probleme laufen; sind es über 100MB, werden die meisten Programme dieser Art anfangen zu stottern, manche stürzen ab, andere laden das gar nicht erst in den Speicher. Bei großen Datensätzen arbeitet man möglichst sequenziell, begrenzt und mit einem entsprechenden Offset, man lädt z.B. nur das in den Speicher, was gerade zum Bearbeiten nötig ist oder auf dem Bildschirm dargestellt werden soll, ansonsten bekommt so einen großen Flaschenhalseffekt mit Drosselung, dass am Ende nichts mehr richtig läuft, sogar das Schließen der Anwendung kann dann versagen oder extrem verzögert werden. Wenn es sich hierbei um WPF handelt und der Ladevorgang mit Bindungen voll durchautomatisiert ist, könnte ein Eingreifen in den Lademechanismus nicht so trivial sein, das müsste man dann möglicherweise selbst schreiben oder zumindest den Ladevorgang in kleinere Portionen einteilen - die Frage ist nur, was passiert, wenn die Daten noch nicht da sind, wenn die Anwendung bereits läuft oder laufen soll, falls man das irgendwie so - und vielleicht auch noch aus einem Nebenthread heraus - zu lösen versuchen würde. Die Ursache für die Misere steckt vermutlich in der Größe der Datensätze als Summe selbst und dem Umstand, das man das alles auf einmal laden will, aber wie gesagt, ist nur so eine Vermutung, so ein Gefühl.
    Das gleichzeitige Erscheinen von Dummheit und Unmündigkeit nach Immanuel Kant ist eines der schlimmsten Dinge, die einem Homo sapiens in geistiger Hinsicht widerfahren können, hat manchmal aber auch durchaus seine Vorteile.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gregor Jasinski“ ()

    Möglicherweise hast du irgendwo einen Flaschenhals. XML-Datei vllt.? Manche nennen das ja auch "Datenbank"

    Ich nutze Sqlite, lade eine ganze DB mit rund 20000 Datensätzen. Könnte zwar auch gefilter aus der DB holen, aber ich habe Filter im Viewmodel und genug Ram, daher lade ich bewusst ganz. Dazu lade ich 1000+ Bilder(Pfade aus den Datensätzen) von einer HDD(nicht SSD) die in einem Datagrid gezeigt werden, das Programm ist nach 7 Sekunden geladen und bereit.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DTF“ ()