Threading / Invoke

01/03/2009 - 15:43 von Kai Wiechers | Report spam
Hallo!
ich versuche gerade Threading in mein .net CF Projekt zu integrieren. Das
Threading an sich funktioniert, aber die Sub die ich in dem separaten Thread
ausführe bekommt einen "NotSupportetException" Fehler. VS gibt mir den Tipp
das ich ein controll.invoke machen soll. Ich habs mal mit
Me.invoke(notification1) in der SMSsenden Sub versucht, aber das brachte mir
einen Fehler ein der mir sagt das notification1 nichtzu system.delegate
konventiert werden kann. Die Doku beim MSDN hat mich leider auch nicht viel
schlauer gemacht. Ich bin noch recht grün hinter den Ohren und würde mich
sehr freuen wenn einer von Euch einen Tipp für mich hat! Vielen dank
schonmal!

Kai

_____________________________________________

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Try
Dim smsthread As New Thread(AddressOf SMSsenden)
smsthread.Start()
Exit Try

Catch ex As Exception
MsgBox("Beim aufrufen der Sendefunktion ist ein Fehler aufgetreten!",
MsgBoxStyle.Critical, "easySMS")
Exit Sub

End Try
End Sub
_______________________________________________

Public Sub SMSsenden()

Button1.Enabled = False

Notification1.Caption = "easySMS"
Notification1.Text = "Die SMS wird an das Gateway übertragen..."
Notification1.InitialDuration = 0
Notification1.Visible = True

'Text codieren
Dim text As String
text = Textcoder(msg_txt.Text)

'URL erzeugen
Dim debugmode As String
If CheckBox1.CheckState = CheckState.Checked Then
debugmode = "1"
Else
debugmode = "0"
End If

Dim absender As String = ""
If smstyp.SelectedItem = "quality" Then
absender = "&from=" & from_txt.Text
End If

Dim url As String = gateway_txt.Text & "u=" & user_txt.Text &
"&p=" & pass_txt.Text & "&to=" & an_txt.Text & "&text=" & text & "&type=" &
smstyp.SelectedItem & "&return_msg_id=1" & "&debug=" & debugmode & absender
Dim request As WebRequest = WebRequest.Create(url)

'Antwort bekommen
Dim response As HttpWebResponse = CType(request.GetResponse(),
HttpWebResponse)
Dim dataStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()

'Antwort Anzeigen
Dim Antwort = responseFromServer
Dim status As String = Strings.Left(Antwort, 3)

Button1.Enabled = True

If status = "100" Then
MsgBox("Versenden erfolgreich." & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "202" Then
MsgBox("Die Empfàngernummer ist ungültig." & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "300" Then
MsgBox("Bitte Benutzer und Passwort angeben!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "301" Then
MsgBox("Bitte Empfànger angeben!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "304" Then
MsgBox("Bitte SMS-Typ wàhlen!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "305" Then
MsgBox("Keinen Text eingegeben!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "401" Then
MsgBox("Text ist zu lang!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "500" Then
MsgBox("Guthaben zu gering!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "900" Then
MsgBox("Benutzer oder Passwort sind falsch!" & vbNewLine,
MsgBoxStyle.Information, "easySMS")
ElseIf status = "902" Then
MsgBox("http API ist für diesen Account nicht aktiviert!" &
vbNewLine, MsgBoxStyle.Information, "easySMS")
Else
MsgBox("Unbekannter fehler!")
End If

Dim msgid As String = Antwort.Substring(4)
'MsgBox(msgid)

'Aufràumen
reader.Close()
dataStream.Close()
response.Close()

If dataset.Tables.Contains("sms") = False Then
Dim smstable As System.Data.DataTable =
dataset.Tables.Add("sms")
smstable.Columns.Add("to", GetType(String))
smstable.Columns.Add("text", GetType(String))
smstable.Columns.Add("type", GetType(String))
smstable.Columns.Add("time", GetType(String))
smstable.Columns.Add("msgid", GetType(String))
smstable.Columns.Add("status", GetType(String))
Dim dr As System.Data.DataRow
dr = smstable.NewRow
Dim Zeit As String = Now
dr("to") = an_txt.Text
dr("text") = msg_txt.Text
dr("type") = smstyp.SelectedItem
dr("time") = Zeit
dr("msgid") = msgid
dr("status") = status
smstable.Rows.Add(dr)
Dim listitem2 As New ListViewItem
listitem2.Text = Zeit
listitem2.SubItems.Add(an_txt.Text)
Dim MSGText As String
MSGText = msg_txt.Text
MSGText = Strings.Left(MSGText, 22) & "..."
listitem2.SubItems.Add(MSGText)
ListView2.Items.Add(listitem2)
ListView2.Items(ListView2.Items.Count - 1).ImageIndex = 0

msg_txt.Text = ""

dataset.WriteXml("\easysms.xml")
Else
Dim smstable As System.Data.DataTable =
dataset.Tables("sms")
Dim dr As System.Data.DataRow
Dim Zeit As String = Now
dr = smstable.NewRow
dr("to") = an_txt.Text
dr("text") = msg_txt.Text
dr("type") = smstyp.SelectedItem
dr("time") = Zeit
dr("msgid") = msgid
dr("status") = status
smstable.Rows.Add(dr)
Dim listitem2 As New ListViewItem
listitem2.Text = Zeit
listitem2.SubItems.Add(an_txt.Text)
Dim MSGText As String
MSGText = msg_txt.Text
MSGText = Strings.Left(MSGText, 22) & "..."
listitem2.SubItems.Add(MSGText)
ListView2.Items.Add(listitem2)
ListView2.Items(ListView2.Items.Count - 1).ImageIndex = 0
msg_txt.Text = ""
'NEU
dataset.WriteXml("\easysms.xml")
End If

If CheckBox3.CheckState = CheckState.Checked Then
Label7.Text = msgid
Timer1.Interval = NumericUpDown1.Value * 1000
Timer1.Enabled = True
End If

Notification1.Visible = False

End Sub
 

Lesen sie die antworten

#1 Peter Götz
02/03/2009 - 09:38 | Warnen spam
Hallo Kai,

ich versuche gerade Threading in mein .net CF Projekt
zu integrieren. Das Threading an sich funktioniert, aber
die Sub die ich in dem separaten Thread ausführe
bekommt einen "NotSupportetException" Fehler.



Es wàre sehr hilfreich, zu wissen an welcher Stelle
in Deinem Code dieser Fehler ausgelöst wird.

VS gibt mir den Tipp das ich ein controll.invoke machen
soll. Ich habs mal mit Me.invoke(notification1) in der
SMSsenden Sub versucht,



Was wolltest Du denn damit erreichen?

aber das brachte mir einen Fehler ein der mir sagt das
notification1 nichtzu system.delegate konventiert werden
kann.



Me.invoke(...)

Erwartet einen Delegaten, also einen Funktionszeiger
der auf eine Prozedur (z.B. Sub) verweist.
Dein Notification1 ist, wenn ich Deinen wenig
überischtlichen Code halbwegs durchschaue, ganz
sicher keine ausführbare Prozedur.


Die Doku beim MSDN hat mich leider auch nicht viel
schlauer gemacht. Ich bin noch recht grün hinter den
Ohren und würde mich sehr freuen wenn einer von
Euch einen Tipp für mich hat! Vielen dank schonmal!



Da gibt es ganz offenbar noch ein erhebliches
Missverstàndnis zum Umgang mit Delegaten.
Du solltest Dir deshalb erst mal die Doku zu
Delegaten ansehen um zu verstehen, was man
damit bezweckt.
Beispiele für Threading und dabei verwendete
Delegaten findest Du z.B. unter

www.gssg.de -> Visual Basic -> VB.net
-> Thread_Invoke
-> BackGroundWorker-Threading
-> Thread Priority

Schau Dir diese Beispiele mal an und versuche zu
verstehen, warum darin bestimmte Prozeduren nicht
direkt sondern eben, um Threadsicherheit zu erreichen,
per Invoke über Delegaten aufgerufen werden.
Zugriffe auf Eigenschaften von Controls, welche im
Hauptthread erzeugt worden sind, dürfen z.B. nicht
direkt aus einem anderen Thread heraus erfolgen, da
solche Zugriffe eben nicht threadsicher sind. Ein
solcher Zugriff sollte bzw. muss per Invoke über
einen Delegaten erfolgen wenn XXX.InvokeRequired
ein True zurückgibt. Details dazu findest Du in den
o.g. Beispielen.

Da Dein Code wg. der vielen, völlig überflüssigen MsgBox-
Aufrufe und der darin vom NewsReader autom. eingefügten
Zeilenumbrüche kaum noch lesbar ist, habe ich ihn nur
kurz überflogen. Soweit ich dabei erkennen kann, enthàlt
Deine Sub SMSsenden() eine Menge an Code, für die
es keinen triftigen Grund gibt, in einem separaten Thread
abzulaufen. Vieles davon kannst Du schon vor dem Start
des Threads aufbereiten und Deiner Threading-Sub dann
ganz einfach als Parameter übergeben. Das macht
Deinen Code, insbesondere in der Thread-Prozedur
einfacher und übersichtlicher und vermindert das Risiko,
dass darin unbehandelte Exceptions auftreten, die Du nur
noch schwer zuordnen kannst.
Soweit ich es erkennen kann, gibt es in Deiner
Sub SMSsenden() einiges was einen Fehler auslösen könnte.
Keiner dieser möglichen Fehler würde in Deinem Code aber
angemessen behandelt werden.

Ellenlange Bandwürmer, wie Dein Else.. if mit den vielen
MsgBox aufrufen kannst Du z.B. so schon um einiges
einfacher und übersichtlicher gestalten:

Dim Messages() as String = _
New String{"StringA", "StringB", "StringC", usw.}

Dim Msg as String
Select Case Status
Case 100
Msg = Messages(0)
Case 200
Msg = Messages(1)
Case 300
Msg= Messages(2)
Case .
Msg = Message(...)
End Select

MsgBox Msg, Sub SMSsenden(), "MsgBoxTitle"

Wenn Du dann Deine Messages auch gleich noch als
Ressourcen ablegst, eröffnet sich damit zusàtzlich
noch die Möglichkeit, Dein Programm, ohne übermàssig
grossen Extra-Aufwand mehrsprachig zu gestalten.

Versuche einzelne Funktionalitàten auf einzelne Subs
oder Functions so zu verteilen, dass Du diese
Funktionalitàten für sich alleine austesten kannst.
Damit erreichst Du automatisch Subs und Functions
die wenig, aber dafür übersichtlichen Code enthalten.
Dieser Code sollte mit entspr. Fehlerbehandlung auch
sicherstellen, dass Deine spàter aufzurufende Thread-
Prozedur die Arbeitsergebnisse Deiner kleinen Subs
und Functions als "fehlerfreie" Parameter übergeben
bekommt.

Wenn Du Code in dieser oder einer anderen Newsgroup
zeigst, dann denke auch bitte daran, dass die meisten
Newsreader Text jeweils automatisch umbrechen, wenn
die Zeilenlànge den Bereich von ca. 70 bis 76 Zeichen
überschreitet und damit die Lesbarkeit einer solchen
Nachricht u.U. sehr negativ beeinflusst wird. Also
besser schon vorher Deinen Code entsprechend
mit sinnvollen Zeilenumbrüchen so formatieren, dass
er auch bei den Lesern einer Newsgroup noch
gut lesbar ankommt. Das erhöht die Chance, dass
sich andere Deinen Code wirklich ansehen, ganz
erheblich.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

Ähnliche fragen