Backgroundworker: Auf Controlls zugreifen

  • VB.NET

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

    Backgroundworker: Auf Controlls zugreifen

    Hey,

    Da momentan einiges geladen werden muss, nimmt dieser Vorgang die Form etwas mit. Durch eine Recherche im Internet kam mir der Backgroundworker unter.

    Das Prinzip habe ich soweit verstanden, jedoch kommt die Meldung, dass auf das Controll nicht zugegriffen werden kann.

    Da habe ich auch herausgefunden, dass man ohne weiteres nicht auf die Controlls zugreifen kann.

    Dazu habe ich auch schon eine Lösung gefunden: ReportProgress und ProgressChanged.

    Leider finde ich jedoch keine funktionierende Möglichkeit diese anzuwenden, auch nach einigen Recherchen bekomme ich es nicht hin.

    Ich lade mit einem PHP Script Namen aus einer Mysql Datenbank und möchte diese in einer Listbox anzeigen. Dies funktioniert auch, jedoch nicht, ohne dass die Form braucht, bis sie geladen ist.

    Wie mache ich das nun?

    Danke schonmal.

    Grüße
    Beispielcode

    VB.NET-Quellcode

    1. Property MeineDaten As Object
    2. Sub Load
    3. Dim bgw As New BackgroundWorker
    4. AddHandler bgw.DoWork, Sub() Daten laden und in meineDaten schaufeln
    5. Addhandler bgw.RunWorkerCompleted, Sub() RaiseEvent SomeOne
    6. bgw.RunWorkerAsync
    7. End Sub
    8. Event SomeOne As EventHandler


    Erklärung:
    Du sagt via dem DoWork-Handler, was passieren soll. Dieser Operation musst du glaube ich sogar jene Variablen mitgeben, die du später abrufbereit haben möchtest. (ByRef-Parameter)
    Mit dem RunWorkerCompleted legst du fest, was passiert wenn das Ding fertig ist. Er macht das dann automatisch.

    Das Event SomeOne hau ich raus, um jedem der mich sieht mitzuteilen das ich fertig bin. Jeder, der was braucht, kann es sich abholen, wie auch deine Form dieses Event beobachten kann (AddHandler SomeOne, AddressOf SubDieDatenAnzeigt).

    Das hat den Sinn das die Form dafür zuständig ist sich zu aktualisieren, nicht die Daten sollen sich in den Vordergrund schieben.

    Deine Form / dein Control wartet also darauf, das SomeOne ausgelöst wird, und wenn es ausgelöst wird hat dies in deinem Kontext die Bedeutung, das er die Daten geladen hat. Er ruft sie aus der Verfügbaren property ab und zeigt sie in Sekundenschnelle an. Während die Daten laden kann das was auch immer passieren noch.

    Anwendungsbeispiel von mir heute:
    Spoiler anzeigen

    Mein programm muss Ordner auslesen und die Dateien darin kennen.
    Da dies 18000 Dateien sind in 900 Unterordnern, dauert das seine Zeit. Bei meinem langsamen Rechner hat das 16 Minuten gebraucht.

    Mein Backgroundworker lädt die Daten in eine Liste, die LifeTime abgerufen werden kann.
    Meine Form zeigt während dem laden immer nur an, wie viele Dateien bereits gefunden wurden, während des ladens kann man alles andere weiterhin im Programm machen.

    Mein Background-Worker-Ende sagt dem Nutzer am Ende nur, das alles geladen wurde und das programm beginnt andere Daten zu laden.

    (Achtung, Code enthält Crap, da es Testcode ist und dieser noch nicht ausgemistet wurde ^-^)

    VB.NET-Quellcode

    1. Public Sub LoadSongsDir()
    2. Dim bgw As New BackgroundWorker
    3. bgw.WorkerSupportsCancellation = True
    4. bgw.WorkerReportsProgress = True
    5. _startTime = Date.Now
    6. AddHandler bgw.DoWork, Sub() CreateFileList("C:\Programme\osu!\Songs", FileList)
    7. AddHandler bgw.RunWorkerCompleted, AddressOf Test
    8. _timer.Start()
    9. AddHandler _timer.Tick, Sub() MainState.Instance.CurrentActionName = String.Format("Analize songs folder - {0} files found - time: {1}", FileList.Count, GetElapsed)
    10. bgw.RunWorkerAsync()
    11. End Sub
    12. Private Sub Test(ByVal sender As Object, ByVal e As EventArgs)
    13. _timer.Stop()
    14. 'Testcode... bei dir nur benötigt um die Form anzuweisen die Daten anzuzeigen
    15. MsgBox("Zeit: " & GetElapsed())
    16. MsgBox(FileList.Count.ToString)
    17. Dim mouses = From file As String In FileList Where file.EndsWith("cursor.png")
    18. MsgBox("Mäuse: " & mouses.Count.ToString)
    19. 'MainState.Instance.CurrentActionName = String.Empty
    20. End Sub
    21. Private Function GetElapsed() As String
    22. Dim now As Date = Date.Now
    23. Dim newDate As Date = now.AddTicks(-1 * _startTime.Ticks)
    24. Return String.Format("{0}:{1}", newDate.Minute, now.Second)
    25. End Function
    26. ' ...
    27. Public Event WindowNameChanged As EventHandler
    28. Private _formName As String = "osu! Skin Creator"
    29. ''' <summary>
    30. ''' The shown name of application in main window
    31. ''' </summary>
    32. ''' <value></value>
    33. ''' <returns></returns>
    34. ''' <remarks></remarks>
    35. Public Property FormName As String
    36. Get
    37. Return String.Format("{0} - Version {1}{2}{3}", _formName, Version, _versionString, If(_actionName.Equals(String.Empty), "", " - " & _actionName))
    38. End Get
    39. Set(ByVal value As String)
    40. If _formName.Equals(value) Then Return
    41. _formName = value
    42. RaiseEvent WindowNameChanged(Me, EventArgs.Empty)
    43. End Set
    44. End Property
    45. Private _actionName As String = String.Empty
    46. Public Property CurrentActionName As String
    47. Get
    48. Return _actionName
    49. End Get
    50. Set(ByVal value As String)
    51. If _actionName.Equals(value) Then Return
    52. _actionName = value
    53. RaiseEvent WindowNameChanged(Me, EventArgs.Empty)
    54. End Set
    55. End Property
    56. ' ...
    57. Private Sub AddHandlers()
    58. '...
    59. AddHandler MainState.Instance.WindowNameChanged, AddressOf RefreshOverview
    60. '...
    61. End Sub


    Das Zauberwort heißt Invoke.

    VB.NET-Quellcode

    1. Me.Invoke(Sub() Me.Label1.Text = "bla")
    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!