Link to home
Start Free TrialLog in
Avatar of feesu
feesu

asked on

VB.NET 2005 - An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

Experts,

While my vb.net windows forms application was running, I got the following runtime error:

-------------------------------------------------------------------------------------------------------------------
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
System.StackOverflowException was unhandled
-------------------------------------------------------------------------------------------------------------------

This comes from the attached code snippet. Now, it started happening every few minutes!

Basically, the code reads from a data feed the names of the stocks and their IDs and saves them into an XML file.
Then I read this into a dataset and while I keep receiving prices, I keep searching for their corresponding stock names from this dataset and display them together. That's when I get this error.



Any help is appreciated.
Dim sStockName As String
        Dim iStockID As Integer
        If dsQuotes_Master.Tables.Count > 0 Then
                        sStockName = CType(dsQuotes_Master.Tables(0).Select("row=" & AR(2)), Array)(0)("Stock_E")
                        iStockID = CType(dsQuotes_Master.Tables(0).Select("row=" & AR(2)), Array)(0)("StockID")
        End If

Open in new window

Avatar of feesu
feesu

ASKER

Experts,

Now, I faced this error in another place. It's in the dataArrival event of the winsock control, where I get the datafeed!
If this means that the feed is too fast or heavy for the application, how come the same control works perfectly with vb6 ?!!

Attached is the code where I faced this error again.

The code broke on the line "Me.Winsock1.GetData(sText)"
  Private Sub Winsock1_DataArrival1(ByVal sender As Object, ByVal e As AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent) Handles Winsock1.DataArrival
        Try
 
            Dim arCR
            Dim sText As String = ""
            Dim Price, Up, Down, AskCnt, AskQty, AskHid, Cross, Qty, QtyL, QtyH, Price1, Price2, Price3, Price4, Price5, Price6, Price7, Price8, Price9, Price10
 
            Me.Winsock1.GetData(sText)
 
            arCR = Split(sText, vbCrLf)
            If Not (Trim(sText) = "" Or UBound(arCR) = 1) Then
 
                For I = 0 To UBound(arCR) - 1
 
                    If (Trim(arCR(0)) <> "") And (Len(arCR(0)) > 1) Then
 
                        arCR(I) = Trim(Mid(Trim(arCR(I)), 1, Len(Trim(arCR(I))) - 2))
                        Me.Text = IIf(bMarketClosed, "Market Closed", "Market Open") & "   -   " & arCR(I)
 
                        AR = Split(arCR(I), "|")
                        If UBound(AR) > 0 Then
 
                            Select Case AR(0)
 
                                Case "$MM"
                                    If AR(3) = 4 Then

Open in new window

I don't think the issue is what you think it is.

A stack overflow exception usually occurs because a method triggers a cyclic call pattern, either by calling itself or by generating an event that results in the same event firing again.

The first thing you should do is look at the call stack when the exception is generated.  This should tell you whether the calls are nested.

Can you provide a complete code sample and/or a complete stack trace for the exception?

Avatar of feesu

ASKER

Hi Steve,

Sure, my scenario is that I use winsock control to receive stock market prices and display them into grids. This winsock used to be use in vb6, and it used to work fine. Today, I needed to make use of vb.net features, but couldnt find that control in .net 2.0 so had to add it manually to my tool box and reference it.

I have got an MDI that has that winsock control that gets triggered with the dataarrival event and from there it spreads the data to the concerned form.

It is important to note that the dataarrival event might be triggered in a fraction of a second. A price may change in less than a second and another type of feed may arrive as well. But didnt expect that this would create such an issue because simply, I still use vb6 to read data and save into the database and it never faced such an error!

I am attaching the code in the MDI/winsock dataarrival event.

 Private Sub Winsock1_DataArrival1(ByVal sender As Object, ByVal e As AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent) Handles Winsock1.DataArrival
        Try
 
            Dim arCR
            Dim sText As String = ""
            Dim Price, Up, Down, AskCnt, AskQty, AskHid, Cross, Qty, QtyL, QtyH, Price1, Price2, Price3, Price4, Price5, Price6, Price7, Price8, Price9, Price10
 
            Me.Winsock1.GetData(sText)
 
            arCR = Split(sText, vbCrLf)
            If Not (Trim(sText) = "" Or UBound(arCR) = 1) Then
 
                For I = 0 To UBound(arCR) - 1
 
                    If (Trim(arCR(0)) <> "") And (Len(arCR(0)) > 1) Then
 
                        arCR(I) = Trim(Mid(Trim(arCR(I)), 1, Len(Trim(arCR(I))) - 2))
                        Me.Text = IIf(bMarketClosed, "Market Closed", "Market Open") & "   -   " & arCR(I)
 
                        AR = Split(arCR(I), "|")
                        If UBound(AR) > 0 Then
 
                            Select Case AR(0)
 
                                Case "$MM"
                                    If AR(3) = 4 Then
                                        bMarketClosed = False
                                    Else
                                        bMarketClosed = True
                                    End If
 
                                Case "$CH"
                                    If AR(11) = 4 Then
                                        bMarketClosed = False
                                    Else
                                        bMarketClosed = True
                                    End If
                                Case "$LL"
                                    ''If dsQuotes_Master.Tables.Count = 1 Then ' to make sure it's not added more than 1 table
                                    'If File.Exists(Me.sXML_Quotes_Master) Then
                                    '    Dim arRows() As DataRow = dsQuotes_Master.Tables(0).Select("ROW=" & Val(AR(2)))
                                    '    If arRows.Length <> 0 Then dsQuotes_Master.Tables(0).Rows.Remove(arRows(0))
                                    'End If
 
                                    'Dim Row1 As DataRow
 
                                    ''Row1 = dtQuotes_Master.NewRow()
                                    'Row1 = dsQuotes_Master.Tables(0).NewRow
 
                                    'Row1("Row") = AR(2)
                                    'Row1("StockID") = AR(3)
                                    'Row1("Stock_E") = AR(4)
                                    'Row1("Stock_A") = AR(5)
 
                                    ''dtQuotes_Master.Rows.Add(Row1)
                                    'dsQuotes_Master.Tables(0).Rows.Add(Row1)
 
                                    ''dsQuotes_Master.Tables.Add(dtQuotes_Master)
                                    'dsQuotes_Master.WriteXml(Me.sXML_Quotes_Master)
                                    ''dsQuotes_Master.Tables.Remove(dtQuotes_Master)
 
                                Case "$TT"
                                    Application.DoEvents()
                                    OnFly_TS.DataArrival(AR)
                                Case "$QQ"
                                    Application.DoEvents()
                                    OnFly_Q.DataArrival(AR)
                                Case "$XX"
                                    Application.DoEvents()
                                    OnFly_Q.DataArrival(AR)
                                Case "$KB"
                                    If bMarketClosed Then Exit Select
                                    OnFly_OB.DataArrival(AR)
                                Case "$KS"
                                    If bMarketClosed Then Exit Select
                                    OnFly_OB.DataArrival(AR)
                            End Select
                        End If
                    End If
                Next
            End If
        Catch ex As Exception
            Me.Text = ex.Message
            'Me.TextBox2.Text = AR(0) & vbCrLf & ex.Message & vbCrLf & vbCrLf & Me.TextBox2.Text
            'MessageBox.Show(ex.Message, "NIC e-360 Streamer", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
 
    End Sub

Open in new window

Avatar of feesu

ASKER

Hi again,
The stack trace doesn't show details it only displays the following:
error: cannot obtain value

This is the title of the error:
An unhandled exception of type 'System.StackOverflowException' occurred in System.Data.dll

Note that depending on the line the code breaks in, it displays a different dll name in the messge.
OK.  Looks like a reentrancy issue.  You don't see this in VB6 because it will run the Winsock control in the same thread as your code, and this means that the Winsock control doesn't fire another event until your code has finished.

In .NET you cannot assume that and so you need to minimise the work that you do inside the event handler and also make sure that the code is thread safe.  This is quite a lot of work to do, I'm afraid.

How much experience do you have of thread-safe programming? Do you know how to use the Monitor class in .NET?

Also, using the Winsock control isn't really a good idea in .NET.  You might find it easier to access the data feed directly.

I'm happy to help you through a code redesign, but it will take a little while...
Avatar of feesu

ASKER

Steve,

I don't know about thread-safe programming.

I looked up an alternative for winsock in .net but most of the comments I read said to use it by manually add it.

If you have an alternative for the winsock in .net then please tell me, and I think that would solve my issue.

Thanks,
Moving away from the Winsock control means using the System.Net and System.Net.Sockets namespaces, depending on exactly what you are trying to do in the Winsock control.

So, my first question is, how are you using the Winsock control?  What are you connecting to and how is it configured?  What are you trying to achieve?
Avatar of feesu

ASKER

I receive data feed from the stock exchange via TCPIP.

Using winsock was the only way in vb6 to do that.

In winsock, I speicify an IP and a Port. And then call the method "Connect" which triggers the "DataArrival" event.

In that event, I extract the needed data and use it as attached in my code.
Have a look here for a good intro to .NET sockets which are the .NET way of using Winsock:
http://msdn.microsoft.com/msdnmag/issues/05/08/HighPerformanceSockets/

See here for the Sockets Reference:
http://msdn2.microsoft.com/en-us/network/bb332030.aspx

You might also want to consider using the TcpClient and UdpClient classes for simpler implementations.

Let me know if you need more assistance, and sorry for the delay getting back to you (work + life = busy!).
Avatar of feesu

ASKER

Hi Steve,
I have tried the sample code in that article. Entered the IP of the feed host in the text box and the port as well. But it gave an error saying that the host is not available.

In winsock, I only specify the host IP and the port then call Connect method. Can you lead me through the code on how to implement the same? I seem not able to achieve it!

Thanks!
Is the server your connecting to a private one?  If not, if you send the details I'll attempt to connect and let you know.  The two most likely issues are (1) that your firewall requires a particular client port number to connect, (2) you are using the wrong protocol (UDP instead of TCP or vice versa).  

I've used the project in the source code (from the link) to connect to Google and view a web page, so it basically works, but it may need to be adapted for your needs.  It works as follows:

1.  It uses Dns.GetHostEntry to lookup IP addresses based on DNS names for both the client and the server
2.  It creates two IPEndPoint objects representing the IP address and port number for the client and the server
3.  It creates a new socket as follows:

  New Socket(myEndpoint.Address.AddressFamily,
                     SocketType.Stream, ProtocolType.Tcp)

The first parameter is indicating that it is an IPv4 or IPv6 address depending on the information it has retrieved about the server.
The second parameter is describing the type of data.  This is important because Tcp and Udp have different default types.  For Udp, you would normally use 'Dgram'.
The final parameter indicates the protocol, in this case Tcp.  It is likely that your solution will need Udp not Tcp.

4.  The Socket.Connect method is called to connect to the specified endpoint, the server.
5.  In the example code, an asynchronous receive pattern is initiated, much like what you are trying to accomplish.  This cycle is started by calling the BeginReceive method.  However, the example code is not attempting to keep on receiving indefinitely so there will be some differences in your code.


So, what code have you produced, is it something you could post?  I'm happy to look over your code for you.
Avatar of feesu

ASKER

Hi Steve,
First, my feed server is an internal one. I filled in the IP in the text box of the sample application and the port but it gave an error as I mentinoed earlier.

If you think that you can help me with that code, then please consider that I need to specify the host and the port then call the method connect to fire the event "DataArrival" in inside that method, I do my work.

If this is not possible with the code you recommended, then please look at the code I attached. I found on the page: http://www.eggheadcafe.com/articles/20020323.asp

Well, it does the job after specifying the details I mentioned, but I, however, cannot find a way to create that event that fires automatically on receving data! Maybe because I am not an expert in .net and that's where I need your help.

Please try to amend this code I have attached in case you think it is more practical to use it, and help me creating that event I am looking for!


Thanks & Best Regards,,
Imports System.Net.Sockets
Imports System.Text
Class TCPCli
    Shared Sub Main()
 
        Dim tcpClient As New System.Net.Sockets.TcpClient()
        tcpClient.Connect("192.0.3.18", 5555)
        Dim networkStream As NetworkStream = tcpClient.GetStream()
        If networkStream.CanWrite And networkStream.CanRead Then
            ' Do a simple write.
            Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes("Is anybody there")
            networkStream.Write(sendBytes, 0, sendBytes.Length)
            ' Read the NetworkStream into a byte buffer.
            Dim bytes(tcpClient.ReceiveBufferSize) As Byte
            networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
            ' Output the data received from the host to the console.
            Dim returndata As String = Encoding.ASCII.GetString(bytes)
            Console.WriteLine(("Host returned: " + returndata))
        Else
            If Not networkStream.CanRead Then
                Console.WriteLine("cannot not write data to this stream")
                tcpClient.Close()
            Else
                If Not networkStream.CanWrite Then
                    Console.WriteLine("cannot read data from this stream")
                    tcpClient.Close()
                End If
            End If
        End If
        ' pause so user can view the console output
        Console.ReadLine()
    End Sub
End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of SteveH_UK
SteveH_UK
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Forced accept.

Computer101
EE Admin