Laden...

[Gelöst] scintilla-Form mit Backgroundworker füllen

Erstellt von Shenzu vor 6 Jahren Letzter Beitrag vor 6 Jahren 3.551 Views
S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren
[Gelöst] scintilla-Form mit Backgroundworker füllen

Hallo zusammen,

folgendes ist gegeben:

  • Form1 mit einer scintilla-Form (Texteditor-Feld wie in Notepad++ verwendet)
  • eine Klasse "FileHandler" die das Verarbeiten von Dateien und deren Inhalt übernimmt

Ein User kann nun in der Form einen Pfad zu einer .txt Datei angeben und mit einem Button-Klick konvertieren lassen (Inhaltlich, ist hier aber irrelevant).

Beim Klick auf den Button wird in meiner FileHandler-Klasse ein Backgroundworker gestartet der die Input-Datei ausliest und entsprechent konvertiert. Nachdem der Backgroundworker fertig ist, soll nun der konvertierte Inhalt in der Form1 scintilla-Box angezeigt werden.

Meine Frage ist nun, wie kann ich meiner Form1 mitteilen, dass der bgworker abgeschlossen ist und der Inhalt nun in der scintilla-Box angezeigt werden soll, ohne die Form via Schleife zu blockieren?

FileHandler.cs - BGworker


public void convertTextFile()
        {    
           
            bgWorker = new BackgroundWorker();
            bgWorker.DoWork += new DoWorkEventHandler(bwDoWorkConvert);            
            bgWorker.RunWorkerAsync();
        }

FileHandler.cs - DoWorkConvert


 private void bwDoWorkConvert(object sender, DoWorkEventArgs e)
        {
            //hier wird der Dateiinhalt konvertiert
        }        

Schonmal vielen Dank für die Hilfe.

PS: ich habe bisher noch nie mit dem bgworker gearbeitet, bin in dieser Hinsicht also ziemlich unerfahren.

H
523 Beiträge seit 2008
vor 6 Jahren

Du musst das Event RunWorkerCompleted des BackgroundWorkers abonnieren und verarbeiten. Das Event wird ausgelöst, wenn (in Deinem Fall) bwDoWorkConvert durchgelaufen ist.

Schau Dir einfach ein Tutorial im Netz dazu an (z. B. das hier)

PS: Den BackgroundWorker nutzt man eigentlich nicht mehr, dafür gibt es heutzutage Tasks.

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Hallo hypersurf,

danke schon mal für die Antwort.

Okay, das RunWorkerCompleted-Event wird korrekt getriggert, aber wie sage ich nun meiner Form, dass das Textfeld aktualisiert werden muss?

D
985 Beiträge seit 2014
vor 6 Jahren

Na ganz einfach mit Textfeld.Text = "Ein Text";

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Na ganz einfach mit Textfeld.Text = "Ein Text";

Ganz so einfach ist es halt nicht, der bgworker läuft ja in einem Objekt meiner Klasse "FileHandler" und hat daher keinen Zugriff auf das Textfeld der Form.

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Hi Coffeebean,

danke auch dir für die Antwort. Ich habe mich ein bisschen eingelesen, ich verstehe leider trotzdem nicht, wie ich das nun zum laufen bekomme.

Wenn ich in folgendem Code versuche via Invoke auf die Textbox zuzugreifen bekomme ich nur Fehler, Invoke ist hier wohl auch nicht verfügbar, muss ich hier irgendwie meinem Worker die GUI mitgeben?


 private void bwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if( e.Cancelled)
            {
                //Cancel
            }
            else if(e.Error != null)
            {
               //Error
            }
            else
            {       
                 //Erfolgreich
                 //do smth
            }
        }

16.834 Beiträge seit 2008
vor 6 Jahren

WPF oder WinForms?

Du hast leider in keinem entsprechenden Forum gepostet.

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Windows Forms

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

dem BackgroundWorker musst Du bestimmt keine GUI bekannt geben.
Die brauchst Du ja auch nur in dem RunWorkerCompleted-Handler, und der Handler gehört nicht zum BackgroundWorker, sondern zu einer Deiner eigenen Klassen.
Du hast also 2 Möglichkeiten:
Entweder gibst Du gibst der FileHandler-Klasse die Form (oder die zu aktualisierenden Controls) mit - das ist die unschöne Variante.
Oder Du verpasst Deiner FileHandler-Klasse ein eigenes Event, das Du von der Form aus abonnieren kannst - das ist die saubere Variante. Dieses Event feuerst Du dann im RunWorkerCompleted-Handler. In einer entsprechenden EventArgs-Klasse gibst Du alle Informationen mit, die die Form kennen muss, um die GUI zu aktualisieren: [FAQ] Eigenen Event definieren / Information zu Events (Ereignis/Ereignisse)

Die Invoke-Geschichten kannst Du Dir beim BackgroundWorker normalerweise sparen, weil sie in dem Thread laufen, in dem RunWorkerAsync aufgerufen wird. Wenn Dein FileHandler nicht schon einen eigenen Thread hat, ist das der GUI-Thread, und Du kannst auf die Controls ohne Invoke zugreifen.

Gruß, MarsStein

EDIT sagt noch: Wenn Du das eigene Event angehst, und die Informationen für die GUI in der FileHandler-Klasse als public Properties vorliegen, kann es auch reichen, in der Form im EventHandler, den sender auf FileHandler zurückzucasten und dann auf diese Properties zuzugreifen. Dann sparst Du Dir eine eigene EventArgs-Klasse. Geschmackssache.

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Hallo MarsStein,

danke für die Antwort.

Ich muss gestehen, ich programmiere nicht so viel und bin daher nicht mit Events, Threads, etc. vertraut. Daher muss ich erstmal verstehen, was diese ganzen Handler, Events. etc. machen.

Ich habe den konvertierten Text tatsächlich als public Property in meiner FileHandler-Klasse vorliegen.

Ich schaue mal, wie weit ich komme.

Danke nochmals an alle für die Beiträge.

Grüße
Shenzu

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Ich habe nun in meiner FileHandler-Klasse ein entsprechendes Event erstellt:


        public event EventHandler WorkerFinished;

        protected virtual void OnWorkerFinished (EventArgs e)
        {
            EventHandler handler = WorkerFinished;
            if(handler != null)
            {
                handler(this, e);
            }
        }

Das Event habe ich entsprechend in meiner Form aboniert


       private void btnConvert_Click(object sender, EventArgs e)
        {
            FH.WorkerFinished += FH_WorkerFinished;    
            FH.convertTextFile();            
        }

        static void FH_WorkerFinished(object sender, EventArgs e)
        {
            Console.WriteLine("Event ausgelöst!");
        }

Ich sehe hier auch die Ausgabe von "Event ausgelöst!" in der Console, allerdings kann ich in FH_WorkerFinished ebenfalls nicht auf meine Form zugreifen !?

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

warum ist FH_WorkerFinished denn static? Das sollte eine Instanzmethode der Form sein, dann kannst Du auch zugreifen 😃

So in der Art:

void FH_WorkerFinished(object sender, EventArgs e)
{
    Console.WriteLine("Event ausgelöst!");
    var fileHandler = (FileHandler)sender;
    myTextField.Text = fileHandler.ConvertedText;
}

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

S
Shenzu Themenstarter:in
16 Beiträge seit 2012
vor 6 Jahren

Ich hatte das so von einem MSDN-Artikel abgekupfert.

Vielen vielen Dank, nun hat es schließlich doch noch funktioniert 😃)))))

Ich sehe schon, ich muss mich mehr mit Events und Threads auseinander setzen, da habe ich wohl noch sehr große Defizite.

Danke nochmals allen für die Mithilfe, der Thread darf geschlossen werden 😃