Werte übergaben aus Thread

12/10/2009 - 12:32 von Peter Haus | Report spam
Hallo NG,

leider blicke ich es mal wieder nicht, wie es geht.

Ich möchte aus einem Thread Werte zurückgeben (String) um diese weiter
zur Verfügung zu haben.
Das den Thread aufrufende Programm ist eine Form.
Nachdem im Thread Daten angekommen sind, habe ich es versucht mit
RaiseEvent onReceiveData(theReply), dies führt zu einem Fehler wenn ich
den String an eine TextBox-Control übergeben will.
RichTextBox1
Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException}}

Ich habe schon eine Möglichkeit gefunden, den String an eine TextBox zu
übergeben. Mit dem Code unten in der Klasse mit dem Thread.
Shared _txtData As RichTextBox
Public Delegate Sub UpdateTextCallback(ByVal text As String)
...
Public Shared Sub UpdateText(ByVal text As String)
_txtData.Text = text
End Sub
...
Dim dlg As New UpdateTextCallback(AddressOf UpdateText)
dlg.Invoke(theReply)
dies funktioniert auch.

Jedoch möchte ich eigentlich nur den zurückgelieferten String, um in
beliebig weiter verarbeiten zu können, eben so, als wenn ein Event in
der Klasse mit dem Thread ausgelöst wird, das mir einen Wert liefert.

In der Form ist CheckForIllegalCrossThreadCalls = False gesetzt.

Leider habe ich etwas Verstàndnis Probleme mit der Materie, ich hoffe
meine Frage ist zu verstehen.

Vielen Dank und Gruss
Peter
 

Lesen sie die antworten

#1 Armin Zingler
12/10/2009 - 13:16 | Warnen spam
Peter Haus schrieb:
Hallo NG,

leider blicke ich es mal wieder nicht, wie es geht.

Ich möchte aus einem Thread Werte zurückgeben (String) um diese weiter
zur Verfügung zu haben.
Das den Thread aufrufende Programm ist eine Form.
Nachdem im Thread Daten angekommen sind, habe ich es versucht mit
RaiseEvent onReceiveData(theReply), dies führt zu einem Fehler wenn ich
den String an eine TextBox-Control übergeben will.
RichTextBox1
Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException}}

Ich habe schon eine Möglichkeit gefunden, den String an eine TextBox zu
übergeben. Mit dem Code unten in der Klasse mit dem Thread.
Shared _txtData As RichTextBox
Public Delegate Sub UpdateTextCallback(ByVal text As String)

Public Shared Sub UpdateText(ByVal text As String)
_txtData.Text = text
End Sub



Eine (Rich)Textbox würde ich nicht als Shared deklarieren!


Dim dlg As New UpdateTextCallback(AddressOf UpdateText)
dlg.Invoke(theReply)
dies funktioniert auch.

Jedoch möchte ich eigentlich nur den zurückgelieferten String, um in
beliebig weiter verarbeiten zu können, eben so, als wenn ein Event in
der Klasse mit dem Thread ausgelöst wird, das mir einen Wert liefert.

In der Form ist CheckForIllegalCrossThreadCalls = False gesetzt.



Das ist schlecht. Das ist außerdem eine Shared Eigenschaft und gilt somit
für alle Controls (also auch Formulare).

Leider habe ich etwas Verstàndnis Probleme mit der Materie, ich hoffe
meine Frage ist zu verstehen.



Ich verstehe das Problem nicht. Du weißt sowohl, dass du das Ergebnis
als Parameter bei RaiseEvent mitgeben kannst, als auch, dass du
mit Invoke arbeiten musst, damit das Control im richtigen Thread
angesprochen wird. Insofern weiß ich jetzt nicht, wo ich helfen könnte.

...Hab mal ein Beispiel gemacht. Neues Projekt anlegen, Button auf Form platzieren
und folgenden Code einfügen:

Private f_Worker As Worker

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
f_Worker = New Worker
AddHandler f_Worker.Done, AddressOf OnWorkerDone
Button1.Enabled = False
f_Worker.Start()

End Sub
Private Sub OnWorkerDone()

If InvokeRequired Then
Invoke(New MethodInvoker(AddressOf OnWorkerDone))
Else
Me.Text = f_Worker.Result
Button1.Enabled = True
f_Worker = Nothing
End If

End Sub


Zusàtzlich Klasse "Worker" hinzufügen:

Imports System.Threading

Public Class Worker
Public Result As String
Private f_Thread As Thread

Public Event Done()

Public Sub Start()

f_Thread = New Thread(AddressOf TMain)
f_Thread.Name = "Worker"
f_Thread.Start()

End Sub
Private Sub TMain()
'bla
Threading.Thread.Sleep(2000)
'bla

Result = "Ergebnis"

RaiseEvent Done()

End Sub
End Class


Du musst in OnWorkerDone aber kein Invoke aufrufen wenn du auf kein
Control zugreifen willst. Du könntest das Ergebnis auch einfach
in einer Variablen in der Form ablegen.

Armin

Ähnliche fragen