I have a loop inside a threaded sub and inside this loop is a simple check that one Boolean is true and another is false, if so it will append some text to a string builder.
This loop is an incoming E-Mail from a socket (hence the thread) which was connected and then threaded. Now the loop works fine apart from where it appends to the string builder (i have tried a normal string also but it the same).
Now this loop accepts packets from port 25 and sends them onto our Exchange server. Collects what exchange sends back and forwards them on to the SMTP client forming a SMTP filter. I no for a fact the loop is working because the E-Mails arrive perfectly that pass through the filter.
This is the code that does not run every time the loop runs
If SendingData And Not DataMessage Then
contentString.Append(SMTPMessage)
End IfThe contentString misses random amounts of text and i can't for the life of me work out why or how the code would not be ran or if it is being ran why all the SMTPMessages don’t make it to the string. Also just to throw another spanner in the works, it does not do this all the time! some times we will run it (sending exactly the same E-Mail from our test SMTP Client) and it works fine....
Below is the complete Sub which is threaded.
Private Sub CreateListeningThread() '' Our Connection to the SMTP Client Dim currentSocket As Socket '' Our Connection to the Exchange Server Dim ExchangeSocket As New TcpClient '' The location of the exchange server Dim exchangeEndPoint As New IPEndPoint(IPAddress.Parse("192.168.111.7"), 25) '' Save The Messages we get back from the two connections Dim SMTPMessage As String '' The Message buffer we use to receive the messages from the connections Dim ArriveArray(2048) As Byte '' The Message buffer we use to send messages to the connections Dim SendArray() As Byte '' For The total bytes of information we received. Dim infoRecieved As Integer '' Used for E-Mail Body Dim DataMessage As Boolean = False Dim SendingData As Boolean = False Dim FirstDataPacket As Boolean = False Dim contentString As New StringBuilder Try '' Open Our Connection to the exchange server.ExchangeSocket.Connect(exchangeEndPoint)
'' The total bytes of information we received.infoRecieved = ExchangeSocket.Client.Receive(ArriveArray)
'' Set our current connection to the connection we established from StartListening()currentSocket = newSocket
'' Save the Connection Ready Message from the Exchange server.SMTPMessage = Encoding.ASCII.GetString(ArriveArray)
'' Get rid of all the trailing empty chars from the buffer that the message did not use '' and split the message back up into a new byte array.SendArray = Encoding.ASCII.GetBytes(Replace(SMTPMessage, Chr(0),
"").ToCharArray()) '' Send the Message to the SMTP client.currentSocket.Send(SendArray, SendArray.Length, 0)
While (True) '' Get the next message from the SMTP Client and forward it onto the '' Exchange server. ReDim ArriveArray(2048)infoRecieved = currentSocket.Receive(ArriveArray)
SMTPMessage = Encoding.ASCII.GetString(ArriveArray)
If LCase(SMTPMessage).StartsWith("data") ThenDataMessage =
TrueSendingData =
True End If If SendingData And Not DataMessage ThencontentString.Append(SMTPMessage)
End If If InStr(SMTPMessage, CrLf & "." & CrLf) ThenDataMessage =
FalseSendingData =
False End IfSendArray = Encoding.ASCII.GetBytes(Replace(SMTPMessage, Chr(0),
"").ToCharArray())ExchangeSocket.Client.Send(SendArray, SendArray.Length, 0)
'' Get the return message from the Exchange server and send it back to the '' SMTP Client. If (DataMessage = True And SendingData = True) Or (DataMessage = False And SendingData = False) Then If SendingData = True Then DataMessage = False ReDim ArriveArray(2048)infoRecieved = ExchangeSocket.Client.Receive(ArriveArray)
SMTPMessage = Encoding.ASCII.GetString(ArriveArray)
SendArray = Encoding.ASCII.GetBytes(Replace(SMTPMessage, Chr(0),
"").ToCharArray())currentSocket.Send(SendArray, SendArray.Length, 0)
End If If LCase(SMTPMessage).StartsWith("quit") Or SMTPMessage.StartsWith("221") Then Exit While End While Catch ex As Exception End Try TryExchangeSocket.Close()
Catch ex As Exception End Try TrymyListener.EndAcceptSocket(currentSocket)
currentSocket.Close()
Catch ex As Exception End TryExchangeSocket =
NothingcurrentSocket =
NothingEMailContent(contentString)
End Sub
Thread Problems – Strange Loop behavior
Jassim Rahma
ner i made it in 2005, passing some things across threads is still safe, its things like setting the value of a text box in the primary thread from a new thread that is not safe.
i think the lock is the way farward, thanks mate.
Thomas Frohberg
Is this written in VS2003 or 2005
I see this code:currentSocket = newSocket and it appears to be a cross thread call; which would mean this was written in VS03 'cause VS05 would throw an error when you ran this.
If this was written in 03, and you've got cross thread calls, then there's no telling how screwy your results might get.
rayou
Lock(1)
myVar = 3
Unlock(1)
Check out Lock, Unlock Functions in the Visual Basic Language Reference. Here is another article that may be beneficial Concurency: What Ever Developer Must Know about MultiThreaded Applications.