Thread|Properties

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von hal2000.

    Thread|Properties

    Hallo, ich bins mal wieder...

    Ich hab ein Problem:

    1. Ich hab eine Klasse, mit einigen Funktionen und Porperties

    2. In meinem Hauptprogramm mache ich nun folgendes:

    VB.NET-Quellcode

    1. Dim test As New Thread(AddressOf Main)
    2. test.Start(New Object() {"xxx", "xx", "x"})


    Ich starte ein neues Thread. Main ist dabei die einstiegsfunktion in meiner anderen Klasse
    Nun zu meinem Problem:

    Ich würde gerne aus meinem Hauptprogramm auf die Properties des gerade erstellten Threads zugreifen, da ich diese abfragen und ändern muss

    Ich hab es schon so versucht:

    VB.NET-Quellcode

    1. Dim neue_klasse As New CTest
    2. Dim test As New Thread(AddressOf neue_klasse.Main)
    3. test.Start(New Object() {"xxx", "xx", "x"})


    CTest ist meine 2. Klasse mit Porperties
    Aber das klappt so nicht...
    Ich hatte mir gedacht das ich nun über:

    VB.NET-Quellcode

    1. Console.WriteLine(neue_klasse.p_status) 'den status des threads ausgeben kann (p_status ist meine Propertie, die ich in der Klasse veränder, jenachdem was das Programm gerade macht)


    Bei dieser Lösungs sagt er mir:

    Quellcode

    1. Fehler bei der Überladungsauflösung, da keine zugreifbare "New" mit diesen Argumenten aufgerufen werden kann:
    2. "Public Sub New(start As System.Threading.ParameterizedThreadStart)": "Option Strict On" erlaubt keine Einschränkungen in impliziten Typkonvertierungen zwischen der Public Sub Main(daten() As Object)-Methode und dem Delegaten "Delegate Sub ParameterizedThreadStart(obj As Object)".
    3. "Public Sub New(start As System.Threading.ThreadStart)": Die Signatur der Public Sub Main(daten() As Object)-Methode ist mit dem Delegaten "Delegate Sub ThreadStart()" nicht kompatibel.


    Hat jemand eine idee ?! denn ich bin langsam am verzweifeln ...
    Also ich verstehe nit was du da machen wilst , aber ich mach es so z.b :D vielleicht hilft dir es weiter.

    VB.NET-Quellcode

    1. Public Structure Connection
    2. Dim ID As String
    3. Dim pos_x As String
    4. Dim pos_y As String
    5. Dim name As String
    6. End Structure
    7. Private Sub ServerListenToNewConnection()
    8. Dim t As New Threading.Thread(AddressOf ListenToConnection)
    9. t.Start(c)
    10. End Sub
    11. Public Sub ListenToConnection(ByVal con As Connection)
    12. Do
    13. Try
    14. Dim Commands As New ServerCommands
    15. Dim tmp As String = con.streamr.ReadLine ' warten, bis etwas empfangen wird...
    16. Console.WriteLine(con.userID & ": " & tmp)
    17. End Try
    18. Loop
    19. End Sub
    Das hilft mir nicht weiter... aber ich versuche mein Problem nochmal genauer zu beschreiben:

    Ich will aus meinem Haupt-Thread heraus ein Neben-Thread starten, und dessen Properties im späteren programmverrlauf im Haupt-Thread abfragen/setzen. Nun sind dies aber selbstdefinierte Properties, in der Klasse, die den Neben-Thread darstellt.

    Wenn ich es mache wie oben in meinem Versuch:

    VB.NET-Quellcode

    1. Dim neue_klasse As New CTest
    2. Dim test As New Thread(AddressOf neue_klasse.Main)
    3. test.Start(New Object() {"xxx", "xx", "x"})


    kann ich über:

    VB.NET-Quellcode

    1. Console.WriteLine(neue_klasse.p_status)


    die status propertie aus meinem Neben-Thread abfragen
    ABER: Das geht nur, wenn ich "Option Strict" ausschalte! Und normalerweise hab ich das gerne an, da es einem hilft Fehler/unsauberen Code zu vermeiden!

    Nun nochmal meine eigentliche Frage: Ist das auch möglich, wenn Option Strict auf On ist (wenn es sein muss auch über umwege :D)?

    hal2000 schrieb:

    Du kannst an Thread.Start() keine Arrays übergeben, denn wie die IDE schon richtig sagt: Der entsprechende Delegat kann nur ein Object verarbeiten, kein Object(). Abhilfe schafft eine Wrapperklasse, die das Array beinhaltet.


    ?! darum geht es gar nicht? das klappt wunderbar und geht auch so! (Mit Option Strict = ON) -> Die Thread.Start() erwartet irgendein Object, egal welches, und deswegen geht das mit dem Array auch wunderbar! Es ist eine einfache Lösung ein Object Array zu übergeben, wenn man mehrere Parameter hat!

    Es geht mir um das Problem das ich, nachdem ich ein Thread gestartet habe die Properties (die ich selbst erstellt habe) abrufen/setzen kann!

    Und da meckert Option Strict, schalte ich es aus geht ja alles, aber ich hab es nunmal gerne an!

    buettner123 schrieb:

    Es ist eine einfache Lösung ein Object Array zu übergeben, wenn man mehrere Parameter hat!

    ...vom schlechten Stil ganz zu schweigen - aber das ist Geschmackssache.

    Ich nehme mal an dass folgendes Szenario gilt:

    VB.NET-Quellcode

    1. Class DataClass
    2. Property MyProp
    3. 'etc...
    4. End Class
    5. Class FirstClass
    6. Sub Main()
    7. Thread.Start(DataClass_Array) --> SecondClass.Main
    8. End Sub
    9. End Class
    10. Class SecondClass
    11. Sub Main(obj As Object) 'obj = Object()
    12. obj(0).MyProp = "hello"
    13. End Sub
    14. End Class

    Liege ich da richtig? Welche Eigenschaft willst du denn nun ändern? Eigenschaften des Threads (von denen du schreibst) können nicht verändert werden, wenn der Thread gestartet wurde. Du meinst wohl eher die Eigenschaft(en) der Datenobjekte, die an den Thread übergeben wurde(n).
    Gruß
    hal2000
    Ich möchte aus meinem Haupt-Thread die Properties der daraus gestarteten Nebenthreads lesen/ändern können!

    Wenn ich schreibe:

    VB.NET-Quellcode

    1. Dim test As New CTest 'CTest ist die Nebenklasse
    2. Dim neues_thread As New Thread(AddressOf test.Main) '"Main" ist die hauptfunktion der Nebenklasse
    3. 'nun kann ich über:
    4. Console.WriteLine(test.p_status) 'die status Property meines gestarteten Threads auslesen (p_status ist eine selbst erstellte Statuseigenschaft, die über eine Enum die Zustände der laufenden Nebenprogramme darstellt)


    ABER wenn ich jetzt Option Strict = On mache, meckert diese, über das "AddressOf test.Main" und will nur ein "AddressOf Main" erlauben mit der im ersten Post erwähnten fehlermeldung!


    BTW: wenn das mit dem Array schlechter Stil ist... kannst du mir evtl sagen wie ich es anders lösen kann? (eigenen Delegaten schreiben?)

    buettner123 schrieb:

    eigenen Delegaten schreiben?

    ...und diesen mit BeginInvoke aufrufen. Damit bekommst du gleich noch die Möglichkeit frei Haus geliefert, aus test.Main einen Wert zurückzuliefern. Noch viel besser ist es, eine Klasse / Struktur zu schreiben und nicht alle Parameter in ein Object-Array zu schreiben. Das bewahrt den Überblick.

    Ich habe dein Problem übrigens reproduzieren können - die Lösung ist ziemlich einfach: Schreibe in die Main-Methodensignatur einfach einen Parameter (As Object) und konvertiere diesen dann in den Typ, den du eigentlich an den Thread übergeben hast. Hierbei hilft dir die selbst erstellte Parameterstruktur sehr.

    VB.NET-Quellcode

    1. Class CTest
    2. Public Sub Main(ByVal obj As Object)
    3. Dim ps As ParamStruct = CType(obj, ParamStruct)
    4. 'etc

    Übrigens: Mit diesem Thread-Salat handelst du dir jede Menge Racebedingungen ein - wenn du die nicht synchronisierst, macht dein Programm nicht das, was es soll. Ich hatte bereits eine in meinem Nachbau mit etwa 20 Zeilen Code und einem (!) weiteren Thread neben dem Mainthread. Du solltest also genau wissen, was du da zustande bringst...
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hal2000“ ()

    Ist es so gemeint?

    VB.NET-Quellcode

    1. Public Class foo
    2. Private mysync As New Object
    3. Private _Bar As Integer
    4. Public Property Bar As Integer
    5. Get
    6. SyncLock (mysync)
    7. Return _Bar
    8. End SyncLock
    9. End Get
    10. Set(ByVal value As Integer)
    11. SyncLock (mysync)
    12. _Bar = value
    13. End SyncLock
    14. End Set
    15. End Property
    16. Public Sub main()
    17. Do
    18. SyncLock (mysync)
    19. If _Bar < 0 Then Exit Do
    20. _Bar += 1
    21. End SyncLock
    22. System.Threading.Thread.Sleep(0)
    23. Loop
    24. End Sub
    25. End Class


    VB.NET-Quellcode

    1. Public Class Form1
    2. Private c As New foo
    3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4. c.Bar = 1
    5. Dim t As New Threading.Thread(AddressOf c.main) With {.IsBackground = True}
    6. t.Start()
    7. End Sub
    8. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    9. Debug.Print(c.Bar)
    10. End Sub
    11. Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
    12. c.Bar = -1
    13. End Sub
    14. End Class

    picoflop schrieb:

    Ist es so gemeint?

    Wenn ich ihn richtig verstanden habe, möchte er zusätzlich noch an foo.main mehrere Parameter übergeben. Der Versuch mit einem Object() scheitert an Option Strict, da der ParameterizedThreadStart-Delegat nur ein einzelnes Objekt in der Signatur erwartet. Damit scheitert auch alles andere, was nicht "Object" ist. Mein Lösungsvorschlag steht oben im Dreizeiler.
    Gruß
    hal2000

    Wenn ich ihn richtig verstanden habe, möchte er zusätzlich noch an foo.main mehrere Parameter übergeben.

    Da er diese Parameter später auslesen und ändern will, wären es Eigenschaften der enthaltenden Klasse. Dann wäre der obige Weg IMHO genauso machbar, oder?