title: vb.net multi-threading activex
body: <p>Ok, I have looked at a bazillion multi-threading examples; all show cute little counters on a form, while you can still access the form, using backgroundworker, or threadpools. I got it. What I don't get is to apply this into a real world application.
  Here's my application, and I don't have a clue on how to multi-thread this;
  Through a 3rd party ActiveX API I read in records to a SQL table at high rate; several million records in 8hours a day.
  While the streaming of the records occurs, I need to go over the records, do some calculations and apply filters, and represent the results in realtime. (filters it down to around a 100 records/day)
  I guess you see already where I'm going with this;
  If I do the calculations/filters on the fly when records are streaming in; it causes the streaming to delay and I loose the connection, So I need to multi-thread the two tasks.</p>
  
  <p>the streaming into SQL table is done as follows: (AxTDAAPIComm is the ActiveX)
  On Form1 :</p>
  
  <pre><code>    Private Sub SubscrBTN_Click(sender As Object, e As EventArgs) Handles SubscrBTN.Click
      AxTDAAPIComm1.Subscribe(StreamOL, tdaactx.TxTDASubTypes.TDAPI_SUB_L1)
  End Sub
  Private Sub AxTDAAPIComm1_OnL1Quote(sender As Object, e As Axtdaactx.ITDAAPICommEvents_OnL1QuoteEvent) Handles AxTDAAPIComm1.OnL1Quote
      SQL.AddStream(e.quote.Symbol, e.quote.Bid, e.quote.Ask, e.quote.Last, e.quote.PrevClose, e.quote.Volume, e.quote.TradeTime, e.quote.QuoteTime, e.quote.TradeDate, e.quote.QuoteDate, e.quote.Volatility, e.quote.OpenInterest, e.quote.UnderlyingSymbol, e.quote.CallPut, e.quote.LastSize, e.quote.MH_LastSize, e.quote.MH_IsQuote, e.quote.MH_IsTrade)
  End Sub
  End Class
  </code></pre>
  
  <p>clicking on the button, invokes the AxTDAAPIComm1_OnL1Quote sub, which streams back records.
  Then in my SQL Class I send it off to my SQL table:</p>
  
  <pre><code>    Public Sub AddStream(Symbol As String, Bid As Single, Ask As Single, Last As Single, PrevClose As Single, Volume As Integer, TradeTime As Integer, QuoteTime As Integer, TradeDate As Integer, Quotedate As Integer, Volatility As Single, OpenInterest As Integer, UnderlyingSymbol As String, CallPut As String, LastSize As Integer, MH_LastSize As Integer, MH_IsQuote As Boolean, MH_IsTrade As Boolean)
      Try
          Dim TradeAmount As Single = 0
          Dim Trade As String = ""
          TradeAmount = LastSize * Last * 100
          Select Case Last
              Case Is = Ask
                  Trade = "Ask"
              Case Is &gt; Ask
                  Trade = "Above Ask"
              Case Is = Bid
                  Trade = "Bid"
              Case Is &lt; Bid
                  Trade = "Below Bid"
              Case Else
                  Trade = "Mid"
          End Select
  
  
          Dim strStream As String = "INSERT INTO OptionStream (Symbol,Bid,Ask,Last,PrevClose,Volume,TradeTime,QuoteTime,TradeDate,QuoteDate,Volatility,OpenInterest,UnderlyingSymbol,CallPut,TradeAmount,Trade,LastSize,MH_LastSize,MH_IsQuote,MH_IsTrade) " &amp; _
                                    "VALUES (" &amp; _
                                    "'" &amp; Symbol &amp; "'," &amp; _
                                    "'" &amp; Bid &amp; "'," &amp; _
                                    "'" &amp; Ask &amp; "'," &amp; _
                                    "'" &amp; Last &amp; "'," &amp; _
                                    "'" &amp; PrevClose &amp; "'," &amp; _
                                    "'" &amp; Volume &amp; "'," &amp; _
                                    "'" &amp; TradeTime &amp; "'," &amp; _
                                    "'" &amp; QuoteTime &amp; "'," &amp; _
                                    "'" &amp; TradeDate &amp; "'," &amp; _
                                    "'" &amp; Quotedate &amp; "'," &amp; _
                                    "'" &amp; Volatility &amp; "'," &amp; _
                                    "'" &amp; OpenInterest &amp; "'," &amp; _
                                    "'" &amp; UnderlyingSymbol &amp; "'," &amp; _
                                    "'" &amp; CallPut &amp; "'," &amp; _
                                    "'" &amp; TradeAmount &amp; "'," &amp; _
                                    "'" &amp; Trade &amp; "'," &amp; _
                                    "'" &amp; LastSize &amp; "'," &amp; _
                                    "'" &amp; MH_LastSize &amp; "'," &amp; _
                                    "'" &amp; MH_IsQuote &amp; "'," &amp; _
                                    "'" &amp; MH_IsTrade &amp; "') "
  
  
          SQLCon.Open()
          SQLCmd = New SqlCommand(strStream, SQLCon)
          SQLCmd.ExecuteNonQuery()
          SQLCon.Close()
  
  
      Catch ex As Exception
          MsgBox(ex.Message)
      End Try
  
  End Sub
  </code></pre>
  
  <p>On my Form I have created a text box, which I use to enter a SQL query statement, which I capture as follows:</p>
  
  <pre><code>   Private Sub cmdQuery_Click(sender As Object, e As EventArgs) Handles cmdQuery.Click
      If txtQuery.Text &lt;&gt; "" Then
          If SQL.HasConnection = True Then
              SQL.RunQueryWL(txtQuery.Text)
              If SQL.SQLDatasetWL.Tables.Count &gt; 0 Then
                  DGVData.DataSource = SQL.SQLDatasetWL.Tables(0)
              End If
          End If
      End If
  End Sub
  </code></pre>
  
  <p>As you can see, it now goes of to the SQL class and runs the Query:</p>
  
  <pre><code>    Public Function HasConnection() As Boolean
      Try
          SQLCon.Open()
          SQLCon.Close()
          Return True
      Catch ex As Exception
          MsgBox(ex.Message)
          Return False
      End Try
  End Function
  Public Sub RunQueryWL(Query As String)
      Try
          SQLCon.Open()
          SQLCmd = New SqlCommand(Query, SQLCon)
          SQLDA = New SqlDataAdapter(SQLCmd)
          SQLDatasetWL = New DataSet
          SQLDA.Fill(SQLDatasetWL)
          SQLCon.Close()
      Catch ex As Exception
          MsgBox(ex.Message)
          If SQLCon.State = ConnectionState.Open Then
              SQLCon.Close()
          End If
      End Try
  End Sub
  </code></pre>
  
  <p>and the result is presented in a datagrid view on my form.
  As you can imagine, querying against a couple million records takes a few seconds, therefore I want to put the AxTDAAPIComm1.Subscribe and AxTDAAPIComm1_OnL1Quote and the RunQueryWL Subs on different threads. </p>
  
  <p>How do I do this?</p>