Sephiroth: VB.NET > Thread mit übergabewerten.

Hi.

Ich hoffe, hier kann mir jemand helfen.

Ich verzweifel gerade daran, wie ich ein Thread starten kann, welcher einen Übergabewert haben möchte:

--VB.NET--------------------------------------------------

Private Sub irgend_eine_Funktion()
    MessageBox.Show(irgend_ein_Wert)
End Sub

Private Sub irgend_eine_Funktion_mit_Werten(ByVal irgend_ein_Wert As Object)
    MessageBox.Show(irgend_ein_Wert)
End Sub

Private Sub Button1Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles hutton1.Click
    Dim th As New System.Threading.Thread(AddressOf irgend_eine_Funktion)
End Sub

----------------------------------------------------

Wie das mit einer Funktion ohne Übergabewerte funktioniert, weiß ich.
Jedoch weiß ich nicht, wie ich einen Übergabewert an diese Funktion sende.

Google macht mich nicht schlau. Und die Gallileo-Handbücher sind genauso verwirrend.

Kann mir einer (wenn möglich) das mal erläutern?

MFG
Sephiroth

  1. Hallo,

    Private Sub irgend_eine_Funktion_mit_Werten(ByVal irgend_ein_Wert As Object)
        MessageBox.Show(irgend_ein_Wert)
    End Sub

    Private Sub Button1Click(ByVal sender As Object,ByVal e As System.EventArgs) Handles hutton1.Click
        Dim th As New System.Threading.Thread(AddressOf irgend_eine_Funktion)
    End Sub

    Und die Gallileo-Handbücher sind genauso verwirrend.

    fand ich zu diesem Thema nicht.
    Ein simples Beispiel, simpler als Deines, das ein eigenes Formular mit dem Namen MessageBox verwendet:

      
    Public Class Form1  
      
        ' Prozedur, die in einem neuen Thread aufgerufen werden soll  
        ' Wie Du richtig erkannt hast, muss der Parameter als Objekt übergeben  
        ' werden  
        Private Sub MyProcedure(ByVal obj As Object)  
            ' Wende die toString-Methode an, die *jedes* Objekt in VB.NET hat,  
            ' um den Übergabeparameter in eine Zeichenkette zu wandeln, das was  
            ' eine Messagebox haben will.  
            MsgBox(obj.toString)  
        End Sub  
      
        Private Sub Button1_Click( _  
            ByVal sender As Object, _  
            ByVal e As System.EventArgs _  
        ) Handles Button1.Click  
            ' Soweit warst Du ja schon.  
            Dim myThread As New System.Threading.Thread(AddressOf MyProcedure)  
      
            ' Du musst nur noch den Thread starten :-)  
            ' Ein typisches "Hallo Welt"-Programm  
            myThread.Start("Hallo Thread!") ' MsgBox erscheint mit dem Inhalt "Hallo Thread!"  
        End Sub  
      
    End Class  
    
    

    Freundliche Grüße

    Vinzenz

    1. Hallo, ergänzend

      es gibt zwei Arten von ThreadStart Delegates:

      • ThreadStart (ohne Parameter)
      • ParameterizedThreadStart (mit object als Parameter)

      Wenn start einem Delegaten eine Methode mit/ohne Parameter direkt in den new Thread() Konstruktor gegeben wird, wählt .Net selbst den richtigen Delegaten aus.

      /* ja, ich weiss, ist C# */
      Thread t = new Thread(delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); });
      t.Start("Frank");

      Allerdings muss man nicht immer einen ganzen kompletten Thread aufmachen, wenn man ihn nicht für die gesamte Lebensdauer braucht.

      Für kurze abgeschlossene Aufgaben empfiehlt sich der ThreadPool mit der Methode QueueUserWorkItem:

      ThreadPool.QueueUserWorkItem(delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); }, "Frank");

      Über das asnychrone Programmiermodell mit BeginInvoke und EndInvoke ist das natürlich auch möglich

      delegate void SampleDelgate(object o);

      SampleDelgate d = delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); };
      d.BeginInvoke("Frank", delegate(IAsyncResult ar)
      {
       AsyncResult aResult = (AsyncResult)ar;
       SampleDelgate temp = (SampleDelgate)aResult.AsyncDelegate;
       temp.EndInvoke(ar);
      }, null);

      Und bitte Threads nicht mit .Abort() abbrechen sondern einfach auslaufen lassen.

      Ciao, Frank

      1. Hallo, ergänzend

        es gibt zwei Arten von ThreadStart Delegates:

        • ThreadStart (ohne Parameter)
        • ParameterizedThreadStart (mit object als Parameter)

        Wenn start einem Delegaten eine Methode mit/ohne Parameter direkt in den new Thread() Konstruktor gegeben wird, wählt .Net selbst den richtigen Delegaten aus.

        /* ja, ich weiss, ist C# */
        Thread t = new Thread(delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); });
        t.Start("Frank");

        Allerdings muss man nicht immer einen ganzen kompletten Thread aufmachen, wenn man ihn nicht für die gesamte Lebensdauer braucht.

        Für kurze abgeschlossene Aufgaben empfiehlt sich der ThreadPool mit der Methode QueueUserWorkItem:

        ThreadPool.QueueUserWorkItem(delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); }, "Frank");

        Über das asnychrone Programmiermodell mit BeginInvoke und EndInvoke ist das natürlich auch möglich

        delegate void SampleDelgate(object o);

        SampleDelgate d = delegate(object o) { Console.WriteLine("Hello {0}!", o.ToString()); };
        d.BeginInvoke("Frank", delegate(IAsyncResult ar)
        {
        AsyncResult aResult = (AsyncResult)ar;
        SampleDelgate temp = (SampleDelgate)aResult.AsyncDelegate;
        temp.EndInvoke(ar);
        }, null);

        Und bitte Threads nicht mit .Abort() abbrechen sondern einfach auslaufen lassen.

        Ciao, Frank

        Danke. Das hilft mir schon gewaltig weiter.

        Jetzt habe ich aber leider ein weiteres Problem:
        (ich poste den code nicht, weil dieser aus dem Gallileo-Computing-Handbuch stammt und minimal abgewandet ist. Mehr infos im weiteren Text)

        Dazu muss ich aber erstmal erläutern, was ich vor habe:

        Ich möchte ein Multiuser-Chat via Socket erstellen. Will mich da erstmals durchfriemeln. Das Gallileo-computing-handbuch beschreibt aber leider nur ein Singe-User-Chat, welcher nur einen einzigsten Socket parrallel annehmen kann.

        Nun versuchte ich logischerweise, das übergebende Socket an einen eigenen Thread weiterzureichen, der das solange handhabt, bis getrennt wird und die hauptfunktion unbeeinflusst weiterläuft.

        Jedoch funktioniert das irgendwie nicht. Sowie ich verbinden will, schmeißt er die verbindung sofort raus und das programm schmiert ab.

        Quellcode kennt wahrscheinlich jeder aus dem Gallileo-Computing-Handbuch. Dort einfach ab "socket.Accept()" den übergabewert an ein eigenen Thread geschickt und das ganze weiterlaufen lassen. (die server.Listen(1) in einer Do While True-Schleife, die quasi nie endet und nur durchs Try/Catch beendet wird)

        Möchte gerne ein möglichst simples beispiel für einen server, wo mehrere clients einfach akzeptiert werden können. (multiuser-chat)

        Wäre für Lösungsbeispiele (möglichst in VB.NET) sehr dankbar.

        Mit freundlichen Grüßen
        Sephiroth

        1. Hi, bitte kein TOFU und kein TUFO :)    Es reicht völlig, wenn du die einzelnen Textpassagen zitierst, auf die du antworten willst, alles andere ist nur Ballast für dieses arme Board ... äh ... Forum.

          Wieviel Sinn macht ein Single-User-Chat? Für Leute, die gern Selbstgespräche führen vielleicht nicht schlecht aber sonst? Für mich ein Programmierbeispiel abseits der Praxis. ;)

          Die suche nach "chat .net socket thread" hätte dich recht schnell zu mehreren  Ergebnissen (auch bei CodeProject)  gebracht, vielleicht nicht gerade immer in VB.net. Aber C# zu VB.Net zu konvertieren ist doch nicht so schwer, ich muss jeden Tag VB6 zu C# umschreiben ;)

          Was soll ein ChatServer machen?

          • Daten annehmen von Clients
          • Daten weitergeben an alle anderen Clients

          Sowas macht man meisten mit zwei sich synchronisierenden Threads. Also System.Threading.Thread, so wie du schon vorhattest.

          • einer welcher eine Verbindung von Clients annimmt und die Daten empfängt
          • einer welche die angenommenen Daten an andere Clients schickt

          Die beiden Threads synchronisieren sich über eine System.Collections.Generic.Queue(Of T). Beide hängen drauf mittels lock oder Monitor.Enter und signalisieren sich mittels Monitor.Pulse(deinQueueObject) und Monitor.Wait() in einer unendlichen[1] Schleife.

          [1] die Beendigung der Schleife regelst du über eine statische Variable nach dem Schema
          while(true)
          {
           if(terminateLoop) break;
          }

          ..., welche du vom Hauptthread (dem UI Thread z.b. setzt)

          Und bitte nicht mit Exceptions irgendwo rausspringen, Exceptions sind böse, besonders die, die du selbst wirfst. ;)

          BTW: Gallileo Literatur ist nicht grad das Gelbe vom Ei. ISBN: 0-7356-1579-9 oder 0-7356-1721-X wären da sicher besser. ;)

          Ciao, Frank