vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Fortgeschrittene
Der Zugriff auf das Steuerelement xy erfolgte von einem andere Thread... 
Autor: Parallax
Datum: 25.02.20 15:51

Hallo,

ich habe die Exception aus dem Titel.
Ausgelöst wird sie durch folgendes Konstrukt:

Eine Sub empfängt bei einem Ereignis Daten aus einer SPS und legt diese in einer Struktur ab, anschließend wird eine weitere Sub aufgerufen, die je nach Datenlage bestimmte Controls im Form aktiviert oder deaktiviert. Bei Controls welche einfach auf der Form liegen stellt dies auch kein Problem dar, nur bei Controls wie einer Groupbox oder einer Registerkarte einer TabControl wird dieser Fehler ausgeworfen. Seltsamerweise auch nur beim einer Registerkarte, eine andere Registerkarte im gleichen TabControl lässt sich problemlos ansprechen.

Ich hab mich schon über diesen Fehler eingelesen, aber werde nicht so richtig schlau daraus. Kann mir jemand erklären was es damit auf sich hat?

Grüße,
Parallax

Am morgen nen Joint und der Tag is dein Freund

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Der Zugriff auf das Steuerelement xy erfolgte von einem andere Thread... 
Autor: Manfred X
Datum: 26.02.20 06:16

Hallo!

Du scheinst - vielleicht ohne es zu wissen - in eine Multithreading-Umgebung geraten zu sein.
Ich vermute, der SPS-Datenlieferant läuft in einem eigenen Thread und ruft Ereignisse Deiner
Oberfläche auf, in denen Du auf Eigenschaften Deiner Controls zugreifen willst.

Deine Angaben sind zu allgemein, um konkrete Hinweise geben zu können, deshalb hier ein
kleines Beispiels zur Verdeutlichung des möglichen Lösungsweges:

In dem WinForms-Formular soll eine Uhr mitlaufen. Dafür gibt es die Routine "MyClock".
Die legt den Thread stets 5 Sekunden schlafen und meldet danach die aktuelle Zeit an
die Ereignisroutine "GetTime". Damit während des Schlafs der Routine der Hauptthread nicht
blockiert wird, läuft 'MyClock' als Hintergrundprozess "GetTimeThread".
Beweis: Du kannst in der Textbox jederzeit Zeichen eintragen oder löschen. Die Oberfläche
ist also nicht blockiert.

Allerdings: Wenn Du in der Ereignisroutine direkt auf Eigenschaften Deiner Controls zugreifen
willst, kommt die bekannte Fehlermeldung. "GetTimeThread" kennt Deine Controls nicht.

Aus diesem Grund benötigst Du den Delegaten "StringIntegerDelegate", der einem Thread bekannt
machen kann, dass eine SUB mit String und Integer-Parameter gerufen wird und dessen Instanz (New)
jeweils angibt, wo diese SUB im Speicher zu finden ist. Diese Informationen plus die
erforderlichen Parameterwerte packst Du in einen Invoke-Aufruf, der die Weiterleitung erledigt.

Ein entsprechendes Vorgehen könnte Dein Problem lösen.

WinForms:
Public Class frmDemo
 
    Dim lblTime As New Label With
        {.Parent = Me, .Width = 100, .Left = 10, .Top = 10}
 
    Dim txtEdit As New TextBox With
        {.Parent = Me, .Width = 100, .Left = 10, .Top = 40, .Height = 150, 
         .Multiline = True}
 
    'Ereignis, dem die aktuelle Uhrzeit gemeldet wird
    Private Event GetTime(ByVal hhmmss As String, ByVal counter As Integer)
 
    'Ein Delegat, der eine Sub incl. eines Parameter des Typs String 
    'und einen zweiten des Typs Integer ansprechen kann
    Delegate Sub StringIntegerDelegate(ByVal str As String, int As Integer)
 
 
 
    Private Sub frmDemo_Load(sender As Object, e As EventArgs) Handles _
      MyBase.Load
 
        'Start der Routine MyClock als Hintergrundprozess
        'Das Formular bleibt verfügbar, während MyClock schläft ... 
        Dim GetTimeThread As New Threading.Thread(AddressOf MyClock)
        GetTimeThread.Start()
    End Sub
 
 
    Private Sub MyClock()
        'Eine Routine, die den Thread 5 sek schlafen legt und dann die 
        'aktuelle Zeit per Ereignisaufruf meldet
        Do
            Static i As Integer
 
            i += 1
            If i > 10000 Then i = 0
 
            Threading.Thread.Sleep(5000)
            RaiseEvent GetTime(Now.ToLongTimeString, i)
        Loop
    End Sub
 
 
    Private Sub frmDemo_GetTime(hhmm As String, counter As Integer) Handles _
      Me.GetTime
        'Der Ereignishandler wird aus dem Thread GetTimeThread gerufen 
 
        'Hier kommt der Fehler: Ungültiger Threadübergreifender Vorgang
        'Der Zugriff auf das Control lblTime erfolgt nicht aus dem Haupthread 
        'lblTime.Text = hhmm
 
        'Auf das Control wird per Invoke zugegriffen. Dafür benötigt man eine 
        'Routine (Showtime), deren Parametertyp (per Delegate) und deren 
        'Speicher-Adresse (AddressOf ...) dem 'blinden' Hintergrundthread 
        'zunächst bekannt gemacht werden müssen
        lblTime.Invoke(New StringIntegerDelegate(AddressOf ShowTime), hhmm, _
          counter)
    End Sub
 
 
    Private Sub ShowTime(ByVal hhmm As String, counter As Integer)
        'Hilfsroutine zum Setzen der Controls-Eigenschaft
        lblTime.Text = hhmm & " - " & counter.ToString
        lblTime.Refresh()
    End Sub
 
End Class


Beitrag wurde zuletzt am 26.02.20 um 06:18:00 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Der Zugriff auf das Steuerelement xy erfolgte von einem andere Thread... 
Autor: Parallax
Datum: 26.02.20 16:36

Hallo Manfred,

danke für die Herleitung, nun ist mir der Vorgang klar.

Die Sub wird von einem Ereignis aufgerufen, welches von einer SPS Bibliothek stammt und nicht von einem UI-Ereignis. Daher der Fehler. Ich konnte dies nun ohne .Invoke relativ einfach mit einem Backgroundworker realisieren. Damit läuft das ganze problemlos durch.

Grüße,
Parallax

Am morgen nen Joint und der Tag is dein Freund

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel