[VB.Net] Multithread - Networking

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo iedereen,

Ik heb een vraag over een multithread applicatie dat ik aan het schrijven was in vb.net. Ik heb een code aangepast die ik gevonden heb op internet om data over een netwerk te sturen. Ik heb de code origineel van een programma waar de code origineel op een formulier stond. Ik heb al alles verwerkt, en er een klasse van gemaakt om dit vaker te gebruiken.

Maar nu komt het probleem. Ik zou dit ook willen verwerken in ddl omdat dit gemakkelijker te gebruiken is, vind ik persoonlijk. Maar als ik de klasse importeer in een class-library zijn er bepaalde types die hij niet meer herkent. Zoals 'Form' (zie de declaratie van 'main', functie 'sendToMain()' & 'serverDis()' ). Ik heb dit nodig om een invoke te doen om de event te initialiseren. Ik vind nergens een manier om dit op te lossen, te omzeilen. Ik heb natuurlijk ook gedacht om de multithread code te implementeren iedere keer in het formulier, maar het moet toch mogelijk zijn om dit de dll te voorzien.

Dan heb ik ook nog een ander probleempje. Bij het afsluiten worden de sub 'endConnection()' opgeroepen. Maar de thread wil niet afsluiten, waardoor ik het programma op zijn geheel niet kan afsluiten. Het hoofdformulier kan worden afgesloten, maar het proces blijft draaien... Heeft daar iemand ook een oplossing voor. Ik heb al vanalles geprobeert, maar ik vind het maar niet

bedankt op voorhand

edit: de code moet nog wat optimalisatie, maar ik zou eerst die willen oplossen

TCPClient.vb
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
 

Imports System.Net.Sockets
Imports System.Text

Public Class TCPClient

    Private clientSocket As New System.Net.Sockets.TcpClient()
    Private serverStream As NetworkStream
    Private readData As String
    Private infiniteCounter As Integer

    Private ctThread As Threading.Thread

    Private t As Boolean = True

    Private main As Form

    Public Event dataArrival(ByVal data As String)
    Public Event serverDisconnected()

    Sub New(ByVal main As Form)

        Me.main = main

    End Sub

    Public Sub sendData(ByVal data As String)

        Try

            Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(data + "$")
            serverStream.Write(outStream, 0, outStream.Length)
            serverStream.Flush()

        Catch ex As Exception

            Throw New Exception("There is no connection with a server")

        End Try

    End Sub

    Private Sub sendToMain()

        If main.InvokeRequired Then

            main.Invoke(New MethodInvoker(AddressOf sendToMain))

        Else

            RaiseEvent dataArrival(readData)

        End If

    End Sub

    Private Sub serverDis()

        If main.InvokeRequired Then

            main.Invoke(New MethodInvoker(AddressOf serverDis))

        Else

            RaiseEvent serverDisconnected()

        End If

    End Sub

    Public Sub connectServer(ByVal ip As String, ByVal port As Integer, ByVal nick As String)

        Try

            readData = "Connected to Chat Server ..."

            sendToMain()

            clientSocket.Connect(ip, port)

            serverStream = clientSocket.GetStream()

            Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(nick + "$")

            serverStream.Write(outStream, 0, outStream.Length)
            serverStream.Flush()

            ctThread = New Threading.Thread(AddressOf getMessage)
            ctThread.Start()

        Catch ex As Exception

            Throw New Exception("Server is not available")

        End Try

    End Sub

    Private Sub getMessage()

        While True

            Try

                serverStream = clientSocket.GetStream()

                Dim buffSize As Integer
                Dim inStream(10024) As Byte

                buffSize = clientSocket.ReceiveBufferSize
                serverStream.Read(inStream, 0, buffSize)

                Dim returndata As String = System.Text.Encoding.ASCII.GetString(inStream)

                readData = returndata

                sendToMain()

            Catch ex As Exception

                t = False
                serverDis()

            End Try

        End While


    End Sub

    Public Sub endConnection()

        clientSocket.Close()

        If Not ctThread Is Nothing Then

            If ctThread.IsAlive Then

                ctThread.Abort()

            End If

        End If

    End Sub

End Class

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Je hebt helemaal die classes 'Form' etc.. In je dll niet nodig.
Je wil nl. net dat dit 'los' staat van enige client-implementatie.
Zoals je class nu is, is deze keihard gekoppeld aan een Windows form. Wat als je dit bv in een console app wilt gebruiken ? Of in een service ? Iets waar er helemaal geen controls aan te pas komen / een applicatie zonder form ?

Wat je kan doen is de Target van je event casten naar een ISynchronizeInvoke (WinForms controls implementeren deze interface), en zo gaan nagaan of een Invoke nodig is of niet.

Een thread wil je ook niet aborten. Je wil 'm nl. op een mooie manier laten stoppen.
Maak een method 'Stop' ofzo op je TcpClient class, die ervoor zorgt dat je getMessage method beëindigd wordt.

Ipv dus:
code:
1
while( true { ... } )

doe je dus zo:
code:
1
2
3
4
5
6
while( stopped == false ) { ... }

public void Stop()
{
    stopped = true;
}

[ Voor 51% gewijzigd door whoami op 09-01-2009 12:32 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt! Ik ga dit onmiddelijk eens bekijken...
Ik laat iets weten!

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Ok.

Je laat maar iets weten.

Om je event te raisen, kan je dus dit doen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void RaiseMyEvent()
{
     EventHandler handler = MyEvent;

     if( handler != null )
     {
           ISynchronizeInvoke t = handler.Target as ISynchronizeInvoke;

           if( t != null && t.InvokeRequired )
           {
                 t.Invoke (handler, .... );
           }
           else
           {
                 handler(this, EventArgs.Empty);
           }
     }
}
Beter is nog om de invocation-list te overlopen, en voor iedere delegate te kijken of er moet ge-invoked worden of niet, natuurlijk.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt Whoami. Het is me gelukt om alles in een dll te gieten. IK heb het getest en het werkt met een gewoon windows form. Kzal nu beginnen aan een paar exception en nog een beetje events. heeft iemand een idee welke events je nog goed kan gebruiken bij een netwerkconnectie

Ik dacht aan:
  • serverconnected
  • serverdisconnected
  • dataArrival
  • dataError ( als de data niet doorgestuurd kan worden )
  • ...
hieronder nog eens de code van de client voor de geïntreseerde. Nogmaals dank !!!

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
Imports System.Net.Sockets
Imports System.Text
Imports System.ComponentModel

    Public Class TCPClient

        Private clientSocket As New System.Net.Sockets.TcpClient()
        Private serverStream As NetworkStream
        Private readData As String
        Private infiniteCounter As Integer

        Private ctThread As Threading.Thread

        Private t As Boolean = True

        Private main As Object

        Public Event dataArrival(ByVal data As String)
        Public Event serverDisconnected()

        Private Delegate Sub delWarnMain()
        Private warnMain As delWarnMain

        Private Delegate Sub delSerDis()
        Private serDisconnected As delSerDis

        Sub New(ByVal main As Object)

            Me.main = main

            warnMain = New delWarnMain(AddressOf sendToMain)
            serDisconnected = New delSerDis(AddressOf serverDis)

            'Me.main = main

        End Sub

        Public Sub sendData(ByVal data As String)

            Try

                Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(data + "$")
                serverStream.Write(outStream, 0, outStream.Length)
                serverStream.Flush()

            Catch ex As Exception

                RaiseEvent serverDisconnected()
                'Throw New Exception("There is no connection with the server")

            End Try

        End Sub

        Private Sub sendToMain()

            If Not main Is Nothing Then

                Dim t As ISynchronizeInvoke = CType(main, ISynchronizeInvoke)

                If Not t Is Nothing And t.InvokeRequired Then

                    t.Invoke(warnMain, Nothing)

                Else

                    RaiseEvent dataArrival(readData)

                End If

            End If

        End Sub

        Private Sub serverDis()

            If Not main Is Nothing Then

                Dim t As ISynchronizeInvoke = CType(main, ISynchronizeInvoke)

                If Not t Is Nothing And t.InvokeRequired Then

                    t.Invoke(warnMain, Nothing)

                Else

                    RaiseEvent serverDisconnected()

                End If

            End If

        End Sub

        Public Sub connectServer(ByVal ip As String, ByVal port As Integer, ByVal nick As String)

            Try

                readData = "Connected to Chat Server ..."

                sendToMain()

                clientSocket.Connect(ip, port)

                serverStream = clientSocket.GetStream()

                Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(nick + "$")

                serverStream.Write(outStream, 0, outStream.Length)
                serverStream.Flush()

                ctThread = New Threading.Thread(AddressOf getMessage)
                ctThread.Start()

            Catch ex As Exception

                Throw New Exception("Server is not available")

            End Try

        End Sub

        Private Sub getMessage()

            t = True

            Do While t = True

                Try

                    serverStream = clientSocket.GetStream()

                    Dim buffSize As Integer
                    Dim inStream(10024) As Byte

                    buffSize = clientSocket.ReceiveBufferSize
                    serverStream.Read(inStream, 0, buffSize)

                    Dim returndata As String = System.Text.Encoding.ASCII.GetString(inStream)

                    readData = returndata

                    sendToMain()

                Catch ex As Exception

                    t = False
                    'serverDis()

                End Try

            Loop

            clientSocket.Close()

        End Sub

        Public Sub endConnection()

            t = False

            sendData("Shuting down")
            serverStream.Close()
            clientSocket.Close()

        End Sub

    End Class

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Ik vind jouw implementatie eerlijk gezegd nog niet helemaal dat ...

Waarom geef je bv nog altijd een form mee als parameter in je constructor ? Da's helemaal niet nodig.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
whoami schreef op vrijdag 09 januari 2009 @ 21:01:
Ik vind jouw implementatie eerlijk gezegd nog niet helemaal dat ...

Waarom geef je bv nog altijd een form mee als parameter in je constructor ? Da's helemaal niet nodig.
Idd..

Maar ik ben niet volledig mee met wat je doe in de code die je voorstelt.
Vooral volgend lijn:


Visual Basic .NET:
1
EventHandler handler = MyEvent;


Je declareert hier een eventHandler handler. Maar wat steek je hier in? Is dit het event die moet worden aangeropen? Maar een event kan toch niet in een variable geplaatst worden... Ik ben hier even niet mee.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:03
Waarom zou je een delegate niet in een andere variable kunnen plaatsen ?

Je maakt hier een kopie van je event-handler, zodanig dat je hier niet te maken kan hebben met threading issues (race condities).
Je stopt eigenlijk de onderliggende delegate in een locale variable (die natuurlijk van hetzelfde type is), en je werkt in je method dan verder op die locale kopie.
Daardoor zorg je ervoor dat er geen eventhandlers kunnen toegevoegd (of verwijderd) worden terwijl de code die de event moet raisen, aan het executen is. (Nou, er kunnen er natuurlijk wel toegevoegd / verwijderd worden, maar je houdt er dan geen rekening mee. Je blijft met dezelfde set werken).

[ Voor 6% gewijzigd door whoami op 10-01-2009 11:43 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb de code opnieuw aangepast en hij werkt nu volledig onafhankelijk, denk ik toch...

Heeft er iemand een idee welke events er allemaal moeten worden aangemaakt?

Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
Imports System.Net.Sockets
Imports System.Text
Imports System.ComponentModel

Public Class TCPClient

    Private clientSocket As New System.Net.Sockets.TcpClient()
    Private serverStream As NetworkStream

    Private ctThread As New Threading.Thread(AddressOf getMessage)

    Private t As Boolean = True

    Public Delegate Sub delDataArrival(ByVal data As String)
    Public Delegate Sub delServerDisconnected()

    Private handlers As New ArrayList()

    Public Custom Event dataArrival As delDataArrival

        AddHandler(ByVal value As delDataArrival)

            handlers.Add(value)

        End AddHandler

        RemoveHandler(ByVal value As delDataArrival)

            handlers.Remove(value)

        End RemoveHandler

        RaiseEvent(ByVal data As String)

            Dim handler As delDataArrival
            Dim t As ISynchronizeInvoke

            For i As Integer = 0 To handlers.Count - 1

                If TypeOf handlers.Item(i) Is delDataArrival Then

                    handler = CType(handlers.Item(i), delDataArrival)
                    t = CType(handler.Target, ISynchronizeInvoke)

                    Dim obj(0) As Object
                    obj(0) = data

                    t.Invoke(handler, obj)

                End If

            Next

        End RaiseEvent

    End Event

    Public Custom Event serverDisconnected As delServerDisconnected

        AddHandler(ByVal value As delServerDisconnected)

            handlers.Add(value)

        End AddHandler

        RemoveHandler(ByVal value As delServerDisconnected)

            handlers.Remove(value)

        End RemoveHandler

        RaiseEvent()

            Dim handler As delServerDisconnected
            Dim t As ISynchronizeInvoke

            For i As Integer = 0 To handlers.Count - 1

                If TypeOf handlers.Item(i) Is delServerDisconnected Then

                    handler = CType(handlers.Item(i), delServerDisconnected)
                    t = CType(handler.Target, ISynchronizeInvoke)

                    t.Invoke(handler, Nothing)

                End If

            Next

        End RaiseEvent

    End Event

    Public Sub connectServer(ByVal ip As String, ByVal port As Integer, ByVal nick As String)

        If Not exitsConnection() Then

            Try

                RaiseEvent dataArrival("Connected to Chat Server ...")

                clientSocket.Connect(ip, port)

                serverStream = clientSocket.GetStream()

                sendData(nick + "$")
                startListing()

            Catch ex As Exception

                Throw New Exception(ex.Message)

            End Try

        End If

    End Sub

    Public Function exitsConnection() As Boolean

        Return clientSocket.Connected

    End Function

    Public Function isListing() As Boolean

        Return ctThread.IsAlive

    End Function

    Public Sub startListing()

        If Not isListing() Then

            ctThread.Start()

        End If

    End Sub

    Private Sub getMessage()

        Dim buffSize As Integer
        Dim inStream(10024) As Byte

        t = True

        Do While t = True

            Try

                If serverStream.DataAvailable Then

                    serverStream = clientSocket.GetStream()

                    If clientSocket.Connected Then

                        buffSize = clientSocket.ReceiveBufferSize
                        serverStream.Read(inStream, 0, buffSize)

                        RaiseEvent dataArrival(System.Text.Encoding.ASCII.GetString(inStream))

                    End If

                End If

            Catch ex As Exception

                t = False
                RaiseEvent serverDisconnected()

            End Try

        Loop

    End Sub

    Public Sub sendData(ByVal data As String)

        If exitsConnection() Then

            Try

                Dim outStream As Byte() = System.Text.Encoding.ASCII.GetBytes(data + "$")
                serverStream.Write(outStream, 0, outStream.Length)
                serverStream.Flush()

            Catch ex As Exception

                RaiseEvent serverDisconnected()
                'Throw New Exception("There is no connection with the server")

            End Try

        End If

    End Sub

    Public Sub endConnection()

        t = False

    End Sub

End Class

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17:02
Als je nu een ArrayList<T> gebruikt hoef je ook niet meer op het delDataArrival type te checken bij aanroepen.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1