GUI-Zugriff von Thread aus in VB.NET

  • WPF

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Dev77.

    GUI-Zugriff von Thread aus in VB.NET

    Hallo miteinander,

    ich entwickle unter VB.NET in Visual Studio 2017. Dabei habe ich gerade eine Applikation, in welcher ich einen Thread aus System.Threading kreiert habe.
    In diesem Thread instanziiere ich einen WPF-XAML-basierende GUI-Dialog, dieser sieht wie folgt aus:

    VB.NET-Quellcode

    1. Class EingabeDialog
    2. Private ReadOnly InitialerPlatzhalterText As String = String.Empty
    3. Sub New(ByVal Title As String, ByVal SetAsTopMost As Boolean, ByVal PlaceHolderText As String)
    4. ' Dieser Aufruf ist für den Designer erforderlich.
    5. InitializeComponent()
    6. InitialerPlatzhalterText = PlaceHolderText
    7. TextInputFeld.Text = PlaceHolderText
    8. Me.Title = Title
    9. Topmost = SetAsTopMost
    10. End Sub
    11. Private Sub BtnDialogOk_Click(sender As Object, e As RoutedEventArgs)
    12. DialogResult = True
    13. End Sub
    14. Public ReadOnly Property EnteredInput As String
    15. Get
    16. Return TextInputFeld.Text
    17. End Get
    18. End Property
    19. Private Sub TxtEnteredInput_GotFocus(sender As Object, e As RoutedEventArgs)
    20. If Trim(TextInputFeld.Text) = InitialerPlatzhalterText Then
    21. TextInputFeld.Text = String.Empty
    22. End If
    23. End Sub
    24. Private Sub TxtEnteredInput_LostFocus(sender As Object, e As RoutedEventArgs)
    25. If Trim(TextInputFeld.Text) = String.Empty Then
    26. TextInputFeld.Text = InitialerPlatzhalterText
    27. End If
    28. End Sub
    29. Private Sub BtnDialogCancel_Click(sender As Object, e As RoutedEventArgs)
    30. DialogResult = False
    31. End Sub
    32. End Class

    Diese Klasse ist einem eigenen File implementiert.
    Innerhalb meines Threads instanziiere ich sie wie folgt:

    VB.NET-Quellcode

    1. Dim LizenzschlüsselEingabe As EingabeDialog = New EingabeDialog(TitelLizenzCheck, True, "Freie Benutzung abgelaufen, bitte Lizenzschlüssel eingeben:")
    2. If LizenzschlüsselEingabe.ShowDialog() = True Then..

    Und in der ersten Zeile crasht mein Thread und ich erhalte folgende Exception: "Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies
    für viele Komponenten der Benutzeroberfläche erforderlich ist."

    Ich weiß, daß dies damit zusammenhängt, daß man nicht so ohne weiteres auf eine GUI von einem anderen Thread aus zugreifen darf, welche in einem anderen
    Thread erzeugt wurde.
    Und ich weiß auch, daß es einige Mechanismen wie Invokes, Delegates usw. gibt. Allerdings habe ich es noch nicht geschafft, die ganze EingabeDialog-Klasse als Delegat
    auszuführen bzw. sie zu invoken. In den gefundenen Beispielen im Internet konnte ich immer nur einzelne Controls wie Buttons, Textfelder usw. sehen, auf welchen ein
    Delegat ausgeführt wurde, nicht jedoch eine ganze GUI-Klasse wie in meinem Fall.
    Hat jemand eine Idee, wie ich das Problem lösen kann?

    Verschoben. Code-Tags eingefügt. ~Thunderbolt

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

    Hey,
    ich bin mir nicht sicher ob es die richtige Methode ist, aber versuche mal dein Thread auf einem STA-Thread wie folgt umzustellen: deinThread.SetApartmentState(ApartmentState.STA)
    Wenn ich dir auf irgendeiner Art und Weise helfen konnte, drück doch bitte den "Hilfreich" Button :thumbup:

    Für VB.NET Entwickler: Option Strict On nicht vergessen!
    Soweit ich weiss kann man in einem Neben-Thread kein GUI erstellen - basta.

    Dev77 schrieb:

    In diesem Thread instanziiere ich einen WPF-XAML-basierende GUI-Dialog
    Lass das.
    (Ich kann mich natürlich auch irren, aber trotzdem denke ich, es wird das einfachste, und der Königsweg sein, es zu lassen)

    Dev77 schrieb:

    VB.NET-Quellcode

    1. DialogResult = True
    Und Option Strict On :!:
    Visual Studio - Empfohlene Einstellungen
    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!
    Hallo an alle,

    erstmal vielen Dank für eure raschen und hilfreichen Antworten!
    Stimmt, das mit dem ApartmentState hat mich schon mal weitergebracht:
    Also mein eigener GUI-Dialog konnte instanziiert und angezeigt werden, nur bekam ich dann das Problem,
    daß ich von meinem Thread aus endlos viele Cross-Thread-Exceptions bekam, also daß mein Thread nicht
    auf eine GUI eines offenbar anderen Thread, in welchem diese erstellt wurde, zugreifen darf.
    Ich habe es dann auch mit dem Invoke- und Delegate-Modell versucht, brachte allerdings auch nicht.

    Ich habe dann den Hinweis, keinen GUI-Dialog aus einem Thread heraus zu erstellen, beherzigt und diese
    Stelle in meinen Hauptthread ausgelagert. Ich triggere dies dann einfach mit bool-Flags.
    Ich weiß, daß es schon irgendwie mit dem Invoken geht, allerdings bin ich mit Threads nicht so bewandert
    und um sicherzugehen, mache ich dann das (vorerst) mal so, wie eben beschrieben.