Instanz in neuem Thread starten

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

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

    Instanz in neuem Thread starten

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend Class frm_ProgressBarAdv
    2. Friend Sub New()
    3. Me.InitializeComponent()
    4. End Sub
    5. Friend Sub New(ByVal iconstructorCurrentValue As Integer,
    6. ByVal iconstructorMaxValue As Integer)
    7. Me.InitializeComponent()
    8. MyOwnProgressBar.Value = iconstructorCurrentValue
    9. MyOwnProgressBar.Maximum = iconstructorMaxValue
    10. End Sub
    11. Private Sub LoadThisForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
    12. MyOwnProgressBar.Minimum = 0
    13. ProgressBarRefresh()
    14. Me.CenterToScreen()
    15. Timer200ms.Enabled = True
    16. End Sub
    17. Private Sub ProgressBarRefresh()
    18. If MyOwnProgressBar.Value < MyOwnProgressBar.Maximum Then
    19. MyOwnProgressBar.Value += 1
    20. Else
    21. MyOwnProgressBar.Value = 0
    22. End If
    23. End Sub
    24. Private Sub Timer_Tick(sender As System.Object, e As System.EventArgs) Handles Timer200ms.Tick
    25. Call ProgressBarRefresh()
    26. End Sub
    27. End Class


    Ich habe eine eigene ProgressBar geschrieben, die im Grunde nichts weiter tun soll also einen Fortschrittsbalken immer von 0..iMaxValue zu inkrementieren und zwar mittels eines 200ms Timers
    Im Hauptform wird die ProgressBar mittels

    VB.NET-Quellcode

    1. Dim _pb As New frm_ProgressBarAdv(0, 100)

    aufgerufen.
    Die ProgressBar öffnet sich auch und dann macht das Hauptprogramm allerlei Dinge die recht rechenintensiv sind. Der Fortschrittsbalken der ProgressBar bewegt sich leider so gut wie gar nicht in dieser Zeit, obwohl der Timer_Tick regelmäßig ausgeführt wird, wird aber die ProgressBar nicht neu gezeichnet. Vermutlich weil die Hauptanwendung die gesamten Ressourcen für sich einnimmt.
    Ich habe jetzt schon einiges probiert um das zu ändern. U.A. mit BackGroundWorker und Invoke, aber so richtig auf eine Lösung bin ich noch nicht gekommen. Wobei ich Invoke bevorzugen würde.
    Wie ist es möglich, dem frm_ProgressBar einen eigenen Thread zuzuordnen, damit dieser unabhängig von der Hauptanwendung aktualisiert und neu gezeichnet wird?
    Jetzt muss ich mich doch noch bezgl dieses Themas melden.
    Ich habe meine MyProgressBar Form jetzt noch etwas erweitert, dahingehend, dass in der MyProgressBar auch Text angezeigt weden kann.
    Jetzt habe ich folgendnes Problem:
    - Sub 1 erstellt MyProgressBar, die ja dann in einem anderen Thread läuft.
    - Solange ich durchgehend von Sub 1 auf die MyProgressBar zugreife und die Property "MyProgressBar.AnzeigeText" ändere, alles kein Thema.
    - Jetzt habe ich aber eine MyProgressBar, die in einer Sub 1 erzeugt wird und eine weitere Sub 2 will auch die "AnzeigeText" Property ändern.
    - Das geht nun furchtbar schief:

    VB.NET-Quellcode

    1. Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement MyOwnProgressBar erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

    wohl, weil die Instanz mittels Sub 1 erstellt wurde und ich daher mit Sub 2 nicht einfach darauf zugreifen kann.
    Obwohl ich MyProgressBar an Sub 2 als Parameter übergabe.
    Wie ändere ich in Sub 2 (vermutlich mittels Invoke) nun denn z.B.

    VB.NET-Quellcode

    1. MyProgressBar.AnzeigeText = "Neuer Text"
    @roepke Mach Dir eine Prozedur, in der Du den Text in die Form hineinreichst und dort invokst Du die Textzuweisung.
    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!
    Erneut ein dickes Dankeschön.
    Einen habe ich noch:
    MyProgressBar ist ein Form, auf dem u.A. die ProgressBar zu finden ist.
    Wird eine MyProgressBar Instanz nun mit

    VB.NET-Quellcode

    1. Dim _frm As New frm_ProgressBar

    erzeugt und dann unmittelbar im Anschluss vom erzeugenden Form versucht eine Property von MyProgressBar zu ändern, kommt es hin und wieder zu einer Exception.
    "Auf ein Element der neuen Instanz kann nicht zugegriffen werden, weil dieses noch nicht erzeugt wurde."
    D.h. der Hauptthread ist halt einfach schneller als das Form erzeugt werden kann.
    Ich frage jetzt in einer

    VB.NET-Quellcode

    1. While MyProgressBar.pbShown = False
    2. Application.DoEvents()
    3. End While

    direkt nach dem Dim ab, ob das Shown-Ereignis von MyProgressBar schon ausgeführt wurde, in dem eine Variable gesetzt wird..
    Find ich persönlich nicht so toll. Gibt es eine elegantere Möglichkeit den Hauptthread warten zu lassen, bis die neue Instanz sicher erzeugt wurde?
    Vielleicht wie bei einem Funktionsaufruf, dass z.B. ein Rückgabewert bei der Erzeugung abgewartet werden muss?
    @roepke Das kommt mir bekannt vor.
    Da die Bar in einem anderen Thread läuft, kommst Du mit DoEvents() nicht ran.
    Mach einfach ein Sleep(500) oder so.
    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!