Backgroundworker funktioniert im Module nicht!

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Backgroundworker funktioniert im Module nicht!

    Hallu.

    Im folgenden seht ihr ein Module, welches ich aus Testzwecken erstellt habe. Ich habe dort eine Funktion erstellt, welche ich per Button in meiner Main Form aktivieren kann. Alles was in WorkerDoWork steht funktioniert eigentlich, bis auf z.B "Form1.Label1.text = 123". Ich vermute, dass liegt daran, dass die Main Form nicht zulässt von einem Module Änderungen anzunehmen oder sowas. Es wäre super, wenn ihr mir da weiterhelfen könntet.

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Module T1
    3. Private Workers As System.ComponentModel.BackgroundWorker
    4. Function MainSettings()
    5. Control.CheckForIllegalCrossThreadCalls = False
    6. Workers = New System.ComponentModel.BackgroundWorker
    7. Workers.WorkerSupportsCancellation = True
    8. AddHandler Workers.DoWork, AddressOf WorkerDoWork
    9. Workers.RunWorkerAsync()
    10. End Function
    11. Private Sub WorkerDoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    12. Form1.Label1.Text = 123
    13. End Sub
    14. End Module


    Edit[02.10.2017]
    Ich antworte auf diesen Thread in Kürze! Ich muss ein andere Problem aus dem Weg räumen, bis ich wieder an diesem Code weiterarbeite und ich würde gerne organisiert arbeiten!
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.

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

    Man greift nicht aus einem Modul in eine Form rein...
    Ich kenne Module unter .NET nur als Extension Module.
    Scheint mir ein MischMasch aus VB6 und .NET zu sein.
    Mach Dir ne Klasse, dort ne Public Property, diese änderst Du in der DoWork und in der Form weist du dem Label den Inhalt der Property zu.
    "Hier könnte Ihre Werbung stehen..."
    @HenryV
    Habe ich bereits versucht, jedoch wird gar nicht erst auf den Label zugegriffen. Soweit ich weiß.

    @MichaHo
    Soweit bin ich leider noch nicht. Ich verstehe nicht ganz, was du mir sagen willst. Jedoch lasse ich keine Antwort ungetestet und schaue mal, ob ich es nach meiner Interpretation schaffe. Danke dir für die Antwort. Ich habe bisher auch nur gehört, dass man Module für andere Sachen nutzt, aber ich wollte meine Kategorien im Programm spalten und nicht alles in eine Class haben. Und da ich mich noch nicht so gut auskenne.. uff, ich weiß nicht. Es ist alles noch verwirrend für mich.

    @EaranMaleasi
    Ich benutze Backgroundworker bisher nur in der Main Class und dort darf ich anscheinend keine Threads übergreifend nutzen. Deshalb habe ich den Check deaktiviert. Ich dachte mir schon das die aus einem Grund auf True ist, ich wüsste aber nicht, warum.
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.
    Ich würde es so machen:

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class Worker
    3. Property _myText As String
    4. Property _myInt As Integer
    5. Public Sub New()
    6. Workers = New BackgroundWorker
    7. Workers.WorkerSupportsCancellation = True
    8. AddHandler Workers.DoWork, AddressOf WorkerDoWork
    9. Workers.RunWorkerAsync()
    10. End Sub
    11. Private Workers As BackgroundWorker
    12. Private Sub WorkerDoWork(sender As Object, e As DoWorkEventArgs)
    13. _myText = "Hier dein Text falls es ein String ist"
    14. _myInt = 123
    15. End Sub
    16. End Class


    In der Form:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private _worker As New Worker
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Label1.Text = _worker._myText
    5. Label2.Text = String.Format("{0}", _worker._myInt)
    6. End Sub
    7. End Class
    "Hier könnte Ihre Werbung stehen..."
    @Sekki Zieh den BGW im esigner auf die Form und feddich.
    Bestenfalls musst Du nen thread-übergreifenden Control-Zugriff per Invoke machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mmal ein Paar Fragen:
    Wozu das Modul? Soll es sowas wie eine Settings-Klasse sein, die dann die Settings in die Form schreibt? Sollte es nicht eher anders herum sein, dass die Form die Settings abfragt, und dann die Controls befüllt?
    Du hast .NET4.5 angegeben, nutzt jedoch nen Backgroundworker, der noch aus .NET 2.0 stammt, und inzwischen nicht nur überholt ist, sondern eigentlich schon völlig verrostet sein sollte.
    Mit Tasks und Async/Await kann man so schön asynchron arbeiten, und muss sich nicht mehr mit einzelnen Threads rumärgern. Schonmal davon gehört?

    Um dein akutes Problem zu lösen, und den Check wieder zu aktivieren, suche mal nach Control.Invoke() bzw. Form.Invoke(). Damit kannst du von einem anderen Thread aus die GUI beinflussen.
    @RodFromGermany
    So habe ich es bisher immer gemacht, dass zerstört die Übersicht über den Code meiner Meinung nach jedoch massiv. Deshalb wollte ich es in die einzelnen Module verschieben. Ich habe ein TabControl und dort stehen 3 Tabs: "Account", "Produkte", "Lieferung" und da ich mit MySQL arbeite, kann dies schon mal sehr viel Code werden, da ich sehr viele Funktionen in jeden einzelnen Tab einbauen möchte. z.B soll mit in Tab: Account einmal die Tabelle ausgelesen werden und einmal will ich sie auch bearbeiten können, vordefinierte Einstellungen nutzen usw. Pro Tab habe ich nun 300 Zeilen Code, insgesamt also 900 Zeilen Code. Dort wird es einfach total ekelhaft, wenn man nicht weiß, wie man sowas in eine Klasse verschiebt oder ein Module. Ich habe bisher die "Class" noch nicht ganz verstanden, irgendwie will mir das nicht in den Kopf rein. Und den Unterschied zwischen Klasse und Module kann ich mir auch nie merken und/oder überhaupt verstehen.

    @MichaHo
    Hey, dass funktioniert super. Jedoch frage ich mich, wie das funktioniert. Ich versuche mal jede Zeile zu erklären und es wäre super, wenn ihr mir kurz sagen könntet, ob mein Verständnis hier richtig ist:

    VB.NET-Quellcode

    1. ​Imports System.ComponentModel 'Damit weiß die Klasse, was der Backgroundworker ist, damit ich es nicht voll ausschreiben muss
    2. Public Class Worker 'Der Name der Klasse, damit ich sie in anderen Klassen ansprechen kann
    3. Property _myText As String 'Definierung, aber warum "Property"? Könnte ich nicht auch "Dim" nutzen?
    4. Property _myInt As Integer 'Definierung, aber warum "Property"? Könnte ich nicht auch "Dim" nutzen?
    5. Private Workers As BackgroundWorker 'Erstellt einen Backgroundworker im Code, jedoch: Warum "Private"? Damit ich aus anderen Klassen nicht aus Versehen darauf zugreife?
    6. Public Sub New() 'Warum "New"? Wird die Sub dann automatisch gelesen? Denn "New2" funktioniert z.B nicht.
    7. Workers = New BackgroundWorker 'Sagt "Workers" dass er ein Backgroundworker sein soll. Aber haben wir den nicht grade schon als solch einen definiert?
    8. Workers.WorkerSupportsCancellation = True 'Erlaubt das abbrechen eines Backgroundworkers
    9. AddHandler Workers.DoWork, AddressOf WorkerDoWork 'Zeigt dem erstellten Worker, welche Subs ihm gehören
    10. Workers.RunWorkerAsync() 'Startet den Worker
    11. End Sub
    12. Private Sub WorkerDoWork(sender As Object, e As DoWorkEventArgs)
    13. _myText = "Hier dein Text falls es ein String ist"
    14. _myInt = 123
    15. End Sub
    16. End Class
    17. Public Class Form1
    18. Private _worker As New Worker 'Wieso reicht "New Worker" bereits aus? Weil die Klasse "Worker" heißt und deshalb vielleicht die Public Sub "New" ist? Oh.....
    19. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    20. Label1.Text = _worker._myText
    21. Label2.Text = String.Format("{0}", _worker._myInt)
    22. End Sub
    23. End Class


    Du musst dir das natürlich nicht durchlesen, ich hätte nur einfach mal gerne.. mehr Verständnis, was sowas angeht.

    @EaranMaleasi
    Ja, vor etwas länger her habe ich von "Tasks und Async/Await" gehört, aber nicht verstanden. Das sagt mir tatsächlich nichts.
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.

    Sekki schrieb:

    da ich mit MySQL arbeite, kann dies schon mal sehr viel Code werden

    In der GUI sollte man von SQL gar nix merken. Denn DB Zugriffe gehören dort gar nicht rein. Schreib dir lieber ne separate Klasse welche den Zugriff zur DB regelt.

    Zudem täte ich nicht alles in Module packen. Nur wenn ich eine Funktion/Variable habe, die ich permanent an 1000 Stellen benötige, würde ich dies in ein Modul auslagern.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Hi,
    Also ich bin auch nicht der Experte, wie die anderen Antworter.
    Sicherlich ist aber ein Task besser als der Backgroundworker, ist aucvh deutlich weniger Code, aber ich bin lediglich auf deinen Code eingegangen.
    Die Klasse Worker wird definiert damit Du sie instanzieren kannst, also eine Instanz davon erstellen kannst. Du könntest davon auch mehrere instanzieren.
    Die Sub New wir jedesmal zuerst aufgerufen, wenn due eine Instanz erstellst, daher wird erst dort ein neuer Backroundworker erstellt.
    Die Propertys (kurze Schreibweise) sind dazu gedacht, das Du von außerhalb darauf zugreifen kannst. Wie eine öffentliche Variable früher in VB6.
    Wenn du die Propertys in voller Schreibweise schreibst, kannst Du sie sogar von außen befüllen...
    In der Form erstellst Du dir eine neue Instanz der Klasse, Sub New wird aufgerufen und der Worker läuft. Daher reicht dort ein New Worker.
    Du könntest sogar hergehen, und Parameter zur Sub New hinzufügen und so die Propertys (die dann Privat sein können) befüllen.
    Die Variable Workers ist deshalb Privat, weil Du sie lediglich innerhalb der Klasse benötigst.
    Ich hoffe ich hab alles richtig erklärt, sonst korrigiert mich bitte.

    P.S. ich arbeite auch viel mit MySql und Sql Server und hab mir dazu eigene Klassen geschrieben, die die Verbindung herstellen und auch die Abfragen verarbeiten, inklusive Update und Parametern.
    "Hier könnte Ihre Werbung stehen..."

    Sekki schrieb:

    Ich habe ein TabControl und dort stehen 3 Tabs
    Das könnten 3 Klassen, je eine zu einem Tab, werden.
    Lagere zusammenhängenden Code aus, kapsele Funktionalität, auch Threads, aber keine BGW, die gehören der Logik nach in die Form, weil sie Events im MainThread senden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Warum reagiert eiglich niemand auf Sekkis Bitte?

    Sekki schrieb:

    Ich versuche mal jede Zeile zu erklären und es wäre super, wenn ihr mir kurz sagen könntet, ob mein Verständnis hier richtig ist:

    Ich beantworte das übrigens auch erstmal nicht (das würde etwas umfangreicher)

    weil in post#1 hab ich sowas entdeckt:

    Sekki schrieb:

    VB.NET-Quellcode

    1. Form1.Label1.Text = 123
    Das heisst, Sekki hat noch nichtmal Option Strict On.
    Visual Studio - Empfohlene Einstellungen

    Ich hab Sekki auf meiner Ignorierliste, das deutet darauf hin, dass er mich entweder arrogant findet (oder sonstige Anwürfe), oder ich fand ihn beratungsresistent - sry - ich erinnere mich nicht mehr.
    Also BeratungsResistenz muss darf ich nun ja fallen lassen - ein Beratungsresistenter würde wohl kaum die o.g. Bitte aussprechen und so einen detaillierter Fragen-Katalog ausarbeiten :thumbsup:

    Aber ehe ich seiner Bitte entspreche (vmtl. wünscht er das ja auch garnet von mir), komme ich doch nochmal mit Visual Studio - Empfohlene Einstellungen
    Jaja, das wird mir oft als Arroganz ausgelegt, aber das ist nunmal meine Meinung: Wenn gegen grundlegendste Grundlagen verstoßen wird, braucht man sich mit anspruchsvollen Problemen wie Threading, Datenbanking im Allgemeinen, MySql-Zugriffen im Besonderen, garnet erst auseinanderzusetzen.

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @ErfinderDesRades Du hast mir die Augen geöffnet. :thumbsup:

    Sekki schrieb:

    VB.NET-Quellcode

    1. Form1.Label1.Text = 123
    Du arbeitest mit dieser unsäglichen mist sch.... grotten usw. VB6-Kompatibilitäts-Instanz.
    Wenn Du wirklich .NET machen willst, musst Du mit Instanzen arbeiten. Gugst Du Dialoge: Instanziierung von Forms und Aufruf von Dialogen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!