| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
Keskustelut - Visual Basic / C# / .NET - VB .NET 2010 Miten saan threadille palautettua formin objekteilta (TextBox) tietoa?Kili 17:39 15.3.12 Listener Luokka jonka sisällä seuraavaa: Public Sub Main() 'Starttaa treadin form loadista tai nyt tällä hetkellä napilta formilta. ListenerThread = New Thread(AddressOf Listen) ListenerThread.Start() End Sub Public Sub Listen() 'Public Shared Sub main() Dim server As TcpListener server = Nothing Try ' Set the TcpListener port Dim port As Int32 = CInt(GetServerPort()) 'Funktio toimii mutta palauttaa aina defaultiksi kirjoitetun "PORT" sanan vaikka threadin käynnistäisi vasta napilla kun kaikki formiin liittyvä on ladattu. Dim ServerAddr As IPAddress = IPAddress.Parse(form.ServerIP_TB.Text) 'Tämä rivi ei toimi suoraan thread luokan sisältä server = New TcpListener(ServerAddr, port) ' Start listening for client requests. server.Start() ............................. ............................ Private Delegate Function ServerPORTInvoker() As String Private Function GetServerPort() As String Dim text As String If form.ServerPort_TB.InvokeRequired Then text = CStr(form.ServerPort_TB.Invoke(New ServerPORTInvoker(AddressOf GetServerPort))) Else text = form.ServerPort_TB.Text End If Return text End Function Elikkä ilmeisesti tuossa delegate tai invoke systeemissä menee jotain pieleen? Kellään sattuisi olemaan yksinkertaista mallia miten saan formilta objekteista (TextBox) haettua tietoja tuon kuuntelia threadin tarpeiksi??? Ja seuraavaksi sitten pitäisi vielä saada kirjoitettua formille logia richtextboxiin weicco 20:25 15.3.12 Siis nappi käynnistää threadin ja threadi kysyy textboxista arvon? Älä herranen aika tee noin. Tuossa on valtava race condition. Syötä sen sijaan textboxin arvo parametrina threadille. Ks. MSDN:stä lisätietoja. http://msdn.microsoft.com/en-us/library/1h2f2459(v=vs.110).aspx editoitu: 23:24 15.3.12 Jari_Kettunen 23:20 15.3.12 Miksi homma täytyy tehdä threadin kautta. Onko kyseessä joku valvomosofta jossa käppyrät päiviittyvät taustalla lennosta itsenäisesti. Vai joku koulutehtävä jossa pitää käyttää threadeja. Ensin haltuun button_click johon koko homma sisään synkronisesti. ps. kotisivusi linkki ei toimi. Kili 08:22 16.3.12 Kyseessä on pieni socket palikka, jonka tarkoitus on ottaa viestejä vastaan ja lähettää TCP/IP:n kautta. Työ aisiahan tämä on ja tarkoitus laittaa käynnistymään tuo kuuntelija formin onloadista. Käsittääkseni net.sockets kuuntelija ilman threadia keskeyttää muun sovelluksen toiminnan? Ei ole vuosiin tarvinnut Visual Basic .net ohjelmointiin koskea joten siksi aika lailla ulalla. Kotisivu ei varmaan ole toiminut aikoihin kun koulukin on käyty jo ajat sitten. Kiitokset Weicolle, kokeilen tuota parametrisointia seuraavaksi. Kili 10:07 16.3.12 Mitenkäs tuolta threadin sisältä pystyy järkevästi lisäämään rivejä formilla olevaan RichTextBoxiin? editoitu: 10:33 16.3.12 Jari_Kettunen 10:32 16.3.12 Seuraavassa Microsoftin koodista käy selväksi miten homman voi tehdä. http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx#Y400 Kili 12:19 16.3.12 Löysin tuon saman ohjeen ja olen sen mukaisesti yrittänyt palautella tietoa richtextboxille mutta en saa sinne tulemaan rivejä. Pitäisikö tuo threadi käynnistää form luokan puolelta? Tällä hetkellä formin button kutsuu kuuntelija luokkaa jossa startataan threadi ja aletaan tehdä juttuja. Tällä hetkellä: Public class TcpListenerClass Delegate Sub SetTextCallback([text] As String) Public Sub Main() Dim Params(1) As Object Params(0) = form.ServerIP_TB.Text Params(1) = form.ServerPort_TB.Text Dim ListenerThread As New Thread(AddressOf Listen) ListenerThread.Start(Params) End Sub Public Shared Sub ADDLineToSVRLOG(ByVal str As String) If form.Server_RTB.InvokeRequired Then form.Server_RTB.Invoke(New Server_RTBDelegate(AddressOf ADDLineToSVRLOG), str) Else form.Server_RTB.AppendText(str & vbNewLine) 'Menee else haaran kautta End If End Sub Public Shared Sub Listen(ByVal Params As Object) ADDLineToSVRLOG("TEST2") 'Kutsu menee läpi ilman virheitä mutta mitään ei ilmesty formin richtext boxiin??? Dim server As TcpListener server = Nothing Try ' Set the TcpListener port Dim port As Int32 = CInt(Params(1)) Dim ServerAddr As IPAddress = IPAddress.Parse(Params(0)) server = New TcpListener(ServerAddr, port) .... .... Menee ja aloittaa kuuntelijan onnistuneesti Form luokasta buttoni joka kutsuu listeneri luokkaa: Dim TcpListenClass As New TcpListenerClass TcpListenClass.Main() Sanokaahan nyt mikä menee väärin kun ei kerran mitään virhettäkään enää pukkaa? Kili 17:12 16.3.12 Tein testin jossa rtb ja kaksi buttonia. Formi luokan koodi: Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Form1 ' This delegate enables asynchronous calls for setting ' the text property on a TextBox control. Delegate Sub SetTextCallback(ByVal [text] As String) ' This thread is used to demonstrate both thread-safe and ' unsafe ways to call a Windows Forms control. Private demoThread As Thread = Nothing Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.demoThread = New Thread( _ New ThreadStart(AddressOf Me.ThreadProcSafe)) Me.demoThread.Start() End Sub Public Sub ThreadProcSafe() Me.SetText("This text was set safely.") End Sub Public Sub SetText(ByVal [text] As String) ' InvokeRequired required compares the thread ID of the ' calling thread to the thread ID of the creating thread. ' If these threads are different, it returns true. If Me.RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText) Me.Invoke(d, New Object() {[text]}) Else Me.RichTextBox1.AppendText(text & vbNewLine) End If End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim Threadi As New Class1 Threadi.main() End Sub End Class Threadi luokan koodi Class1: Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Class1 ' This delegate enables asynchronous calls for setting ' the text property on a TextBox control. Delegate Sub SetTextCallback(ByVal [text] As String) ' This thread is used to demonstrate both thread-safe and ' unsafe ways to call a Windows Forms control. Private demoThread1 As Thread = Nothing Public Sub main() Me.demoThread1 = New Thread( _ New ThreadStart(AddressOf ThreadProcSafe1)) Me.demoThread1.Start() End Sub Public Sub ThreadProcSafe1() Me.SetText1("This text was set safely 2.") End Sub Public Sub SetText1(ByVal [text] As String) ' InvokeRequired required compares the thread ID of the ' calling thread to the thread ID of the creating thread. ' If these threads are different, it returns true. If Form1.RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText1) Form1.Invoke(d, New Object() {[text]}) Else Form1.RichTextBox1.AppendText(text & vbNewLine) 'Tähän mennään #1# End If End Sub Public Sub New() End Sub Protected Overrides Sub Finalize() MyBase.Finalize() End Sub End Class Kun button1 kirjoittelee tekstiä formi luokan sisällä niin kaikki menee oikein ja teksti ilmestyy rtb komponenttiin. Button 2 menee #1# kautta ja tekstiä tai mitään virhettä ei tule? Eli miten tuolta toisen luokan sisältä onnistutaan kirjoitamaan formille tavaraa? editoitu: 18:32 16.3.12 Jari_Kettunen 18:25 16.3.12 Luokalle parametrina lomake niin viritys toimii. (me:n viljely koodissa on turhaa) vb Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Class1 Delegate Sub SetTextCallback(ByVal [text] As String) Private demoThread1 As Thread = Nothing Private parentForm As Form1 Public Sub main(f As Form1) 'Laitetaan isä talteen parentForm = f demoThread1 = New Thread( _ New ThreadStart(AddressOf ThreadProcSafe1)) demoThread1.Start() End Sub Public Sub ThreadProcSafe1() SetText1("This text was set safely 2.") End Sub Public Sub SetText1(ByVal [text] As String) 'Laitetaan isälomakkeelle data kohdalleen If parentForm.RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText1) parentForm.Invoke(d, New Object() {[text]}) Else parentForm.RichTextBox1.AppendText(text & vbNewLine) 'Tähän mennään #1# End If End Sub Protected Overrides Sub Finalize() MyBase.Finalize() End Sub End Class Ja pääformi vb Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Form1 ' This delegate enables asynchronous calls for setting ' the text property on a TextBox control. Delegate Sub SetTextCallback(ByVal [text] As String) ' This thread is used to demonstrate both thread-safe and ' unsafe ways to call a Windows Forms control. Private demoThread As Thread = Nothing Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click demoThread = New Thread( _ New ThreadStart(AddressOf Me.ThreadProcSafe)) demoThread.Start() End Sub Public Sub ThreadProcSafe() SetText("This text was set safely.") End Sub Public Sub SetText(ByVal [text] As String) If RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText) Invoke(d, New Object() {[text]}) Else RichTextBox1.AppendText(text & vbNewLine) End If End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim Threadi As New Class1 'Huomaa parametrina isäntä lomake Threadi.main(Me) End Sub End Class Kili 18:38 16.3.12 Kiitoksia! En nyt enää ole ohjelman parissa mutta tuli vielä tuosta rivistä: 'Huomaa parametrina isäntä lomake Threadi.main(Me) mieleen, että miten onnistuu lomakkeen vieminen parametrinä jos threadille annetaan jo kaksi string tyyppistä parametria ja lomake parametri? Meneekö ihan parametri taulukkona jonka tyyppi on object? editoitu: 19:42 16.3.12 Jari_Kettunen 19:37 16.3.12 Näiden threadien kanssa sekoaa usein omaan näppäryyteensä ja kannattaa olla tarkkana. Tässähän nyt luodaan luokka jonka main metodia kutsuttiin joka sitten käynnisti luokan sisäisen threadin. Koodista käynee esille mitä tarkoitan. Esimerkkikoodissa käynnistetäään threadit jotka kirjoittavat ikiloopissa RichTextBoxin vuorotellen ja toiset painikkeet sitten pysäyttävät threadin. Lisäksi treadit kannattaa sammuttaa ennen lomakkeen sulkeutumista vaikkapa koodin esittämällä tavalla. vb Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Form1 Delegate Sub SetTextCallback(ByVal [text] As String) Private demoThread As Thread = Nothing Private Threadi2 As Class1 Public Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If demoThread Is Nothing Then demoThread = New Thread( _ New ThreadStart(AddressOf Me.ThreadProcSafe)) Else demoThread.Abort() demoThread = New Thread( _ New ThreadStart(AddressOf Me.ThreadProcSafe)) End If demoThread.Start() End Sub Public Sub ThreadProcSafe() Dim i As Integer = 1 While True System.Threading.Thread.Sleep(1000) SetText("a" + i.ToString()) i = i + 1 End While End Sub Public Sub SetText(ByVal [text] As String) If RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText) Invoke(d, New Object() {[text]}) Else RichTextBox1.AppendText(text & ",") End If End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click If Threadi2 Is Nothing Then Threadi2 = New Class1 Else Threadi2.StopThread() Threadi2 = New Class1 End If 'Huomaa parametrina isäntä lomake Threadi2.main(Me) End Sub Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click Threadi2.StopThread() Threadi2 = Nothing End Sub Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click demoThread.Abort() demoThread = Nothing End Sub Private Sub Form1_FormClosing(sender As System.Object, e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing If Not demoThread Is Nothing Then demoThread.Abort() End If If Not Threadi2 Is Nothing Then Threadi2.StopThread() End If End Sub End Class ja luokka vb Imports System Imports System.ComponentModel Imports System.Threading Imports System.Windows.Forms Public Class Class1 Delegate Sub SetTextCallback(ByVal [text] As String) Private demoThread1 As Thread = Nothing Private parentForm As Form1 Public Sub main(f As Form1) 'Laitetaan isä talteen parentForm = f demoThread1 = New Thread( _ New ThreadStart(AddressOf ThreadProcSafe1)) demoThread1.Start() End Sub Public Sub StopThread() demoThread1.Abort() End Sub Public Sub ThreadProcSafe1() Dim i As Integer = 1 While True System.Threading.Thread.Sleep(1000) SetText1("B" + i.ToString()) i = i + 1 End While End Sub Public Sub SetText1(ByVal [text] As String) 'Laitetaan isälomakkeelle data kohdalleen If parentForm.RichTextBox1.InvokeRequired Then Dim d As New SetTextCallback(AddressOf SetText1) parentForm.Invoke(d, New Object() {[text]}) Else parentForm.RichTextBox1.AppendText(text & ",") 'Tähän mennään #1# End If End Sub Protected Overrides Sub Finalize() MyBase.Finalize() End Sub End Class editoitu: 20:30 16.3.12 Jari_Kettunen 20:20 16.3.12 Kili kirjoitti: Kiitoksia! En nyt enää ole ohjelman parissa mutta tuli vielä tuosta rivistä: 'Huomaa parametrina isäntä lomake Threadi.main(Me) mieleen, että miten onnistuu lomakkeen vieminen parametrinä jos threadille annetaan jo kaksi string tyyppistä parametria ja lomake parametri? Meneekö ihan parametri taulukkona jonka tyyppi on object? No tämä on vähän jo olipohjelmoinnin asioita. Jos katsot metodia joka threadin käynnistyksessä annetaan ja mietit mikä on metodin luokkaympäristö ja mitä se näkee niin ehkä homma vähän aukeaa. Net-ympäristössä kannattaa ensin pois oppia globaaleiden muuttujien käytöstä. Sinällään jos tässä sanoo jotain luokkien constructoreista niin tulee silmille heti. On kaksi koulukuntaa toinen on sitä mieltä että constuktoriin pitää laittaa kaikki parametrit ja sitten tehdä niin monta wrapperi constuctoria että vanha koodi toimii. Itse taas pidän enemmän public propertyistä ja "parametrittomasta" constructorista. Helpottaa vastuullista luokan rajapinnan laajentamista vahingoittamatta vanhan koodin toimintaa. Button 3 seuraavassa koodissa tai button 4 vanhalla tavalla. Kieleksi kannattaa vaihtaa c# syntyy luettavampaa koodia. C# using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication5 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { label1.Text = new Class1().Say(); } private void button2_Click(object sender, EventArgs e) { label1.Text = new Class1("Hello","World").Say(); } private void button3_Click(object sender, EventArgs e) { label1.Text = new Class1() { Hip = "Hello", Hei = "World" }.Say(); } private void button4_Click(object sender, EventArgs e) { var x =new Class1(); x.Hip = "Hello"; x.Hei = "World"; label1.Text=x.Say(); } } } Ja luokka C# using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WindowsFormsApplication5 { public class Class1 { public string Hip {get;set;} public string Hei { get; set; } public Class1() { Hip = "Hello"; Hei = "World"; } public Class1(string hip,string hei) { Hip = hip; Hei = hei; } public string Say() { return Hip + " " + Hei; } } } |
![]() Haku
|