Threading help... threads???

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Keith Mills

    Threading help... threads???

    Hello, please find attached a basic outline of what I am attempting to
    accomplish... basically I want to create a number of THREADS (which I can do
    fine), but I then need a method for them to be able to communicate with each
    other, either through a message loop, or some other manner. I ALSO need to
    be able to CALL specific functions / subs WITHIN a thread, based on what
    another THREAD is doing... here is the attached code... WHEN I click on the
    CALLOUT button, it HANGS the thread until it's execution is done:

    *** This is where the issue lies - when its called from the main gui, the
    thread running it blocks...
    Private Sub Button1_Click(B yVal sender As System.Object, ByVal e As
    System.EventArg s) Handles Button1.Click
    LineArray(txtCa llOutOn.Text).c allout()
    End Sub
    ***

    CODE BELOW --
    Imports System.Threadin g

    Imports System.Componen tModel 'for CancelEventArgs

    Imports System.Runtime. InteropServices 'COM support

    Public Class Form3

    Inherits System.Windows. Forms.Form

    'Public WithEvents mVoiceBocx As VoiceBocxLib.Vo iceBocx ' VoiceBocx control

    Private iNrTrunks As Integer 'maximum number of available trunks

    Private LineArray() As TrunkThread

    #Region " Windows Form Designer generated code "

    Public Sub New()

    MyBase.New()

    'This call is required by the Windows Form Designer.

    InitializeCompo nent()

    'Add any initialization after the InitializeCompo nent() call

    End Sub

    'Form overrides dispose to clean up the component list.

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing Then

    If Not (components Is Nothing) Then

    components.Disp ose()

    End If

    End If

    MyBase.Dispose( disposing)

    End Sub

    'Required by the Windows Form Designer

    Private components As System.Componen tModel.IContain er

    'NOTE: The following procedure is required by the Windows Form Designer

    'It can be modified using the Windows Form Designer.

    'Do not modify it using the code editor.

    Friend WithEvents txtIterations As System.Windows. Forms.TextBox

    Friend WithEvents ListBox1 As System.Windows. Forms.ListBox

    Friend WithEvents ToTrunk As System.Windows. Forms.TextBox

    Friend WithEvents Label2 As System.Windows. Forms.Label

    Friend WithEvents FromTrunk As System.Windows. Forms.TextBox

    Friend WithEvents Label1 As System.Windows. Forms.Label

    Friend WithEvents btnStart As System.Windows. Forms.Button

    Friend WithEvents btnExit As System.Windows. Forms.Button

    Friend WithEvents Button1 As System.Windows. Forms.Button

    Friend WithEvents Button2 As System.Windows. Forms.Button

    Friend WithEvents txtCallOutOn As System.Windows. Forms.TextBox

    Friend WithEvents txtBridge As System.Windows. Forms.TextBox

    <System.Diagnos tics.DebuggerSt epThrough()> Private Sub InitializeCompo nent()

    Me.txtIteration s = New System.Windows. Forms.TextBox

    Me.btnStart = New System.Windows. Forms.Button

    Me.ListBox1 = New System.Windows. Forms.ListBox

    Me.ToTrunk = New System.Windows. Forms.TextBox

    Me.Label2 = New System.Windows. Forms.Label

    Me.FromTrunk = New System.Windows. Forms.TextBox

    Me.Label1 = New System.Windows. Forms.Label

    Me.btnExit = New System.Windows. Forms.Button

    Me.Button1 = New System.Windows. Forms.Button

    Me.txtCallOutOn = New System.Windows. Forms.TextBox

    Me.Button2 = New System.Windows. Forms.Button

    Me.txtBridge = New System.Windows. Forms.TextBox

    Me.SuspendLayou t()

    '

    'txtIterations

    '

    Me.txtIteration s.Location = New System.Drawing. Point(32, 48)

    Me.txtIteration s.Name = "txtIterati ons"

    Me.txtIteration s.TabIndex = 0

    Me.txtIteration s.Text = ""

    '

    'btnStart

    '

    Me.btnStart.Loc ation = New System.Drawing. Point(160, 48)

    Me.btnStart.Nam e = "btnStart"

    Me.btnStart.Siz e = New System.Drawing. Size(96, 23)

    Me.btnStart.Tab Index = 1

    Me.btnStart.Tex t = "Launch Thread"

    '

    'ListBox1

    '

    Me.ListBox1.Loc ation = New System.Drawing. Point(16, 88)

    Me.ListBox1.Nam e = "ListBox1"

    Me.ListBox1.Siz e = New System.Drawing. Size(544, 355)

    Me.ListBox1.Tab Index = 4

    '

    'ToTrunk

    '

    Me.ToTrunk.Loca tion = New System.Drawing. Point(528, 48)

    Me.ToTrunk.Name = "ToTrunk"

    Me.ToTrunk.Size = New System.Drawing. Size(33, 20)

    Me.ToTrunk.TabI ndex = 10

    Me.ToTrunk.Text = "11"

    '

    'Label2

    '

    Me.Label2.Locat ion = New System.Drawing. Point(496, 48)

    Me.Label2.Name = "Label2"

    Me.Label2.Size = New System.Drawing. Size(27, 21)

    Me.Label2.TabIn dex = 9

    Me.Label2.Text = "To"

    '

    'FromTrunk

    '

    Me.FromTrunk.Lo cation = New System.Drawing. Point(448, 48)

    Me.FromTrunk.Na me = "FromTrunk"

    Me.FromTrunk.Si ze = New System.Drawing. Size(40, 20)

    Me.FromTrunk.Ta bIndex = 8

    Me.FromTrunk.Te xt = "0"

    '

    'Label1

    '

    Me.Label1.Locat ion = New System.Drawing. Point(376, 48)

    Me.Label1.Name = "Label1"

    Me.Label1.Size = New System.Drawing. Size(67, 21)

    Me.Label1.TabIn dex = 7

    Me.Label1.Text = "Use trunks:"

    '

    'btnExit

    '

    Me.btnExit.Loca tion = New System.Drawing. Point(272, 48)

    Me.btnExit.Name = "btnExit"

    Me.btnExit.Size = New System.Drawing. Size(40, 24)

    Me.btnExit.TabI ndex = 11

    Me.btnExit.Text = "Exit"

    '

    'Button1

    '

    Me.Button1.Loca tion = New System.Drawing. Point(608, 24)

    Me.Button1.Name = "Button1"

    Me.Button1.TabI ndex = 12

    Me.Button1.Text = "Button1"

    '

    'txtCallOutOn

    '

    Me.txtCallOutOn .Location = New System.Drawing. Point(608, 56)

    Me.txtCallOutOn .Name = "txtCallOut On"

    Me.txtCallOutOn .Size = New System.Drawing. Size(72, 20)

    Me.txtCallOutOn .TabIndex = 13

    Me.txtCallOutOn .Text = "2"

    '

    'Button2

    '

    Me.Button2.Loca tion = New System.Drawing. Point(608, 96)

    Me.Button2.Name = "Button2"

    Me.Button2.TabI ndex = 14

    Me.Button2.Text = "Button2"

    '

    'txtBridge

    '

    Me.txtBridge.Lo cation = New System.Drawing. Point(608, 128)

    Me.txtBridge.Na me = "txtBridge"

    Me.txtBridge.Si ze = New System.Drawing. Size(72, 20)

    Me.txtBridge.Ta bIndex = 15

    Me.txtBridge.Te xt = "0"

    '

    'Form3

    '

    Me.AutoScaleBas eSize = New System.Drawing. Size(5, 13)

    Me.ClientSize = New System.Drawing. Size(736, 454)

    Me.Controls.Add (Me.txtBridge)

    Me.Controls.Add (Me.Button2)

    Me.Controls.Add (Me.txtCallOutO n)

    Me.Controls.Add (Me.Button1)

    Me.Controls.Add (Me.btnExit)

    Me.Controls.Add (Me.ToTrunk)

    Me.Controls.Add (Me.Label2)

    Me.Controls.Add (Me.FromTrunk)

    Me.Controls.Add (Me.Label1)

    Me.Controls.Add (Me.ListBox1)

    Me.Controls.Add (Me.txtIteratio ns)

    Me.Controls.Add (Me.btnStart)

    Me.Name = "Form3"

    Me.Text = "Form3"

    Me.ResumeLayout (False)

    End Sub

    #End Region

    Private Sub Form3_Load(ByVa l sender As System.Object, ByVal e As
    System.EventArg s) Handles MyBase.Load

    Try

    'Dim mVoiceBocx1 As VoiceBocxLib.Vo iceBocx

    'mVoiceBocx1 = New VoiceBocxLib.Vo iceBocx

    'iNrTrunks =
    mVoiceBocx1.Get InstalledChanne ls(VoiceBocxLib .RES_TYPE.RES_T YPE_Trunk)

    'mVoiceBocx1 = Nothing

    Catch ex As Exception

    Trace("Error getting installed trunks =" & ex.Message)

    Return

    End Try

    Trace("There are " & iNrTrunks & " trunks available")

    End Sub

    Public Sub Trace(ByVal Text As String)

    If (ListBox1.Items .Count > 800) Then

    ListBox1.Items. RemoveAt(0)

    End If

    ListBox1.Items. Add(Text)

    ListBox1.Select edIndex = ListBox1.Items. Count - 1

    End Sub

    Private Sub btnLaunchThread _Click(ByVal sender As System.Object, ByVal e As
    System.EventArg s) Handles btnStart.Click

    Dim iTrunk As Integer

    Dim iToTrunk As Integer

    Dim iFromTrunk As Integer

    Trace("Starting threads to service trunks")

    iToTrunk = ToTrunk.Text

    iFromTrunk = FromTrunk.Text

    If (iToTrunk > iNrTrunks - 1) Then

    Trace("Last trunk to use changed to last available")

    iToTrunk = iNrTrunks - 1

    ToTrunk.Text = iToTrunk 'don't start more trunks then we have

    ToTrunk.Invalid ate()

    End If

    If (iFromTrunk > iToTrunk) Then

    Trace("First trunk to use changed to last requested")

    iFromTrunk = iToTrunk

    FromTrunk.Text = iFromTrunk 'don't start more trunks then we have

    FromTrunk.Inval idate()

    End If

    'Allocate array of LineHandler objects to keep track of

    'lines so that we can shut them down properly.

    'It is a good practice to check if "new" succeeded but

    'it is not done here for simplicity.

    ReDim LineArray(iToTr unk - iFromTrunk)

    Dim Line As New TrunkThread

    For iTrunk = iFromTrunk To iToTrunk

    Line = New TrunkThread

    LineArray(iTrun k - iFromTrunk) = Line

    'pass parameters to the new thread

    Line.iTrunk = iTrunk

    Line.MainForm = Me

    'this delegate will handle thread start event

    Dim ts As ThreadStart

    ts = New ThreadStart(Add ressOf Line.main)

    'create new thread

    Dim wrkThread As Thread

    wrkThread = New Thread(ts)

    Line.CurrentThr ead = wrkThread

    Trace("Starting new thread for trunk " & iTrunk)

    wrkThread.Apart mentState = ApartmentState. STA 'default is MTA

    wrkThread.Name = iTrunk.ToString () 'for easier tracing

    wrkThread.IsBac kground = True

    wrkThread.Start ()

    Next

    btnStart.Enable d = False

    End Sub

    Private Sub ButtonExit_Clic k(ByVal sender As System.Object, ByVal e As
    System.EventArg s) Handles btnExit.Click

    'We must not exit if the call is in progress, need to check it in
    Form.Closing

    Close() 'Closing event for the Form is not triggered without this

    End Sub

    'validate from/to trunk values

    Private Sub Trunk_KeyPress_ From(ByVal sender As Object, ByVal e As
    KeyPressEventAr gs) Handles FromTrunk.KeyPr ess

    'If not numeric, tell Windows that we handled the event.

    'Backspace is allowed for corrections.

    If (Not (Char.IsNumber( e.KeyChar)) And (e.KeyChar <> ChrW(8))) Then '8 is
    backspace

    e.Handled = True

    End If

    End Sub

    Private Sub Trunk_KeyPress_ To(ByVal sender As Object, ByVal e As
    KeyPressEventAr gs) Handles ToTrunk.KeyPres s

    'If not numeric, tell Windows that we handled the event.

    'Backspace is allowed for corrections.

    If (Not (Char.IsNumber( e.KeyChar)) And (e.KeyChar <> ChrW(8))) Then '8 is
    backspace

    e.Handled = True

    End If

    End Sub

    Private Sub MTInboundForm_C losed(ByVal sender As System.Object, ByVal e As
    System.EventArg s) Handles MyBase.Closed

    Application.Exi t()

    End Sub

    Private Sub MTInboundForm_C losing(ByVal sender As System.Object, ByVal e As
    CancelEventArgs ) Handles MyBase.Closing

    e.Cancel = False 'don't cancel exit

    'if lines never started

    If (LineArray Is Nothing) Then

    Return

    End If

    Dim iLineCount As Integer = LineArray.Lengt h

    Do

    Dim iStillRunning As Integer = 0

    Dim iLine As Integer = 0

    For iLine = 0 To iLineCount - 1

    'if thread already exited, continue

    If (Not ((LineArray(iLi ne).CurrentThre ad) Is Nothing)) Then

    LineArray(iLine ).Shutdown(Fals e)

    If (Not ((LineArray(iLi ne).CurrentThre ad) Is Nothing)) Then

    iStillRunning = iStillRunning + 1

    End If

    End If

    Next

    If (0 = iStillRunning) Then 'we are done

    Return

    End If

    Dim strMsg As String = "There are still " + Str(iStillRunni ng) + " running
    threads."

    Dim Result As DialogResult = MessageBox.Show ( _

    strMsg + " Do you want to try again (No will force the exit as is)?", _

    "Exiting Application", MessageBoxButto ns.YesNo)

    If (DialogResult.N o = Result) Then

    'force exit even if some threads not stopped yet

    For iLine = 0 To iLineCount - 1

    If (Not ((LineArray(iLi ne).CurrentThre ad) Is Nothing)) Then

    LineArray(iLine ).Shutdown(True ) 'force exit

    End If

    Next

    Return 'we are done

    End If

    Loop While (True)

    End Sub

    Private Sub Button1_Click(B yVal sender As System.Object, ByVal e As
    System.EventArg s) Handles Button1.Click

    'LineArray(txtC allOutOn.Text). bcallout = True

    LineArray(txtCa llOutOn.Text).c allout()

    End Sub

    Private Sub Button2_Click(B yVal sender As System.Object, ByVal e As
    System.EventArg s) Handles Button2.Click

    LineArray(txtCa llOutOn.Text).c onf(txtBridge.T ext)

    LineArray(txtBr idge.Text).conf (txtCallOutOn.T ext)

    End Sub

    End Class

    Class TrunkThread

    'Public WithEvents mVoiceBocx As VoiceBocxLib.Vo iceBocx ' VoiceBocx control

    Public MainForm As Form3

    Public iTrunk As Integer

    Public bcallout As Boolean

    Public CurrentThread As Thread

    Private bincall As Boolean

    Public Property test()

    Get

    End Get

    Set(ByVal Value)

    End Set

    End Property

    Public Sub main()

    Dim iThreadId As Integer

    iThreadId = Thread.CurrentT hread.GetHashCo de()

    MainForm.Trace( "In the new thread " & iThreadId & " on trunk " & iTrunk)

    Try

    'mVoiceBocx = New VoiceBocxLib.Vo iceBocx

    MainForm.Trace( "Voice Object instantiated on trunk " & iTrunk)

    'mVoiceBocx.Tru nkAssign(iTrunk )

    MainForm.Trace( "Trunk assigned " & iTrunk)

    Catch e As COMException

    MainForm.Trace( "Error starting Voice Object =" & (e.ErrorCode And 65535))

    Return

    Catch e As Exception

    MainForm.Trace( "Error using Voice Object =" & e.Message)

    Return

    End Try

    MainForm.Trace( "Incoming call handler set on trunk " & iTrunk)

    Application.Run ()

    End Sub

    Public Sub callout()

    MainForm.Trace( "OutDial for trunk " & iTrunk)

    Try

    'mVoiceBocx.Mak eCall("474-7031", True)

    MainForm.Trace( "Playing greeting on trunk " & iTrunk)

    'mVoiceBocx.Pla yFile("hello.vo x",
    VoiceBocxLib.SO UNDFILE_TYPE.SO UNDFILE_TYPE_Vo x24K)

    Do

    Thread.CurrentT hread.Sleep(100 )

    Loop

    Catch e As COMException

    Dim iCode As Integer

    iCode = e.ErrorCode And 65535

    'If (mVoiceBocx.Err orNumber = iCode) Then

    'MainForm.Trace ("Hangup detected on trunk " & iTrunk)

    'Else

    ' MainForm.Trace( "Call processing ended with code " & iCode)

    'End If

    Finally

    Try

    MainForm.Trace( "Disconnect ing on trunk " & iTrunk)

    'mVoiceBocx.Dis connectCall()

    Catch e As COMException

    MainForm.Trace( "Exception " & (e.ErrorCode And 65535) & "on trunk " &
    iTrunk)

    End Try

    bincall = False

    MainForm.Trace( "Ready for calls on trunk " & iTrunk)

    End Try

    End Sub

    Public Sub conf(ByVal iWho As Integer)

    MainForm.Trace( "Conf for trunk " & iTrunk)

    Try

    'mVoiceBocx.Tru nkListenTo(Voic eBocxLib.RES_TY PE.RES_TYPE_Tru nk, iWho)

    MainForm.Trace( "Conf " & iTrunk & " and " & iWho)

    Do

    Thread.CurrentT hread.Sleep(100 )

    Loop

    Catch e As COMException

    Dim iCode As Integer

    iCode = e.ErrorCode And 65535

    'If (mVoiceBocx.Err orNumber = iCode) Then

    'MainForm.Trace ("Hangup detected on trunk " & iTrunk)

    'Else

    ' MainForm.Trace( "Call processing ended with code " & iCode)

    'End If

    Finally

    Try

    MainForm.Trace( "Disconnect ing on trunk " & iTrunk)

    'mVoiceBocx.Dis connectCall()

    Catch e As COMException

    MainForm.Trace( "Exception " & (e.ErrorCode And 65535) & "on trunk " &
    iTrunk)

    End Try

    bincall = False

    MainForm.Trace( "Ready for calls on trunk " & iTrunk)

    End Try

    End Sub

    Public Sub Shutdown(ByVal bForceExit As Boolean)

    If (bincall And (False = bForceExit)) Then

    Return

    End If

    'mVoiceBocx.Tru nkUnassign()

    'mVoiceBocx.Med iaUnassign()

    CurrentThread.A bort()

    CurrentThread = Nothing

    End Sub

    Private Sub mVoiceBocx_Inco mingCall() 'Handles mVoiceBocx.Inco mingCall

    bincall = True

    Try

    MainForm.Trace( "Rings for trunk " & iTrunk)

    'mVoiceBocx.Ans werCall()

    MainForm.Trace( "Playing greeting on trunk " & iTrunk)

    'mVoiceBocx.Pla yFile("hello.vo x",
    VoiceBocxLib.SO UNDFILE_TYPE.SO UNDFILE_TYPE_Vo x24K)

    Do

    Thread.CurrentT hread.Sleep(100 )

    Loop

    Catch e As COMException

    Dim iCode As Integer

    iCode = e.ErrorCode And 65535

    'If (mVoiceBocx.Err orNumber = iCode) Then

    'MainForm.Trace ("Hangup detected on trunk " & iTrunk)

    'Else

    ' MainForm.Trace( "Call processing ended with code " & iCode)

    'End If

    Finally

    Try

    MainForm.Trace( "Disconnect ing on trunk " & iTrunk)

    'mVoiceBocx.Dis connectCall()

    Catch e As COMException

    MainForm.Trace( "Exception " & (e.ErrorCode And 65535) & "on trunk " &
    iTrunk)

    End Try

    bincall = False

    MainForm.Trace( "Ready for calls on trunk " & iTrunk)

    End Try

    End Sub 'incoming call

    Private Sub mVoiceBocx_Call erHangUp() 'Handles mVoiceBocx.Call erHangUp

    MainForm.Trace( "Caller hungup " & iTrunk)

    End Sub

    End Class


  • Chris Dunaway

    #2
    Re: Threading help... threads???

    After a quick glance, it appears as if you have an endless loop. You
    have these lines of code in the callout function:

    Do
    Thread.CurrentT hread.Sleep(100 )
    Loop

    It will never exit that loop. Secondly, you appear to be calling back
    into the main form from the thread. This is also not a good idea, and
    the Windows forms controls are not thread safe. At the end of this
    post, I added a small class that you can use to create derived classes
    that run in their own thread. The thread wrapper class just
    encapsulates a thread and make it easy to create classes that run on
    that thread.

    We tried using VoiceBocx with your approach but utimately decided on a
    different approach. We wrote it so that each line basically ran in a
    loop on a separate thread. In the loop the thread would check a "call
    queue" to see if there were any calls to be made. If so, they would
    remove the call record from the queue and make the call. They would
    then store the call progress results to a separate results queue.
    There was a single thread running that would process that queue.

    We used a single queue to service all lines on the application, but if
    you have a small number of lines, you could have a separate queue for
    each line, but whatever process fills the queues would have to have
    some sort of distribution logic so that all lines would keep busy.

    Basically we had a thread that would query the database or file for the
    phone numbers to be called. These would be placed on a call queue.

    Each vbocx line would run on its own thread in a loop until told to
    stop. The loop would check the queue to see if there were any calls to
    make. If so, it would grab a call from the queue and make the call and
    deliver the message. It would then place the call progress result
    (Busy, No Answer, etc) on a result queue. If there were no calls on
    the queue to be made, the Vbocx thread would wait for a short time for
    any inbound calls, it would then repeat the loop.

    There was another thread whose job was to process the items in the
    result queue and update the database with the results.


    Here is a class that you derive your TrunkThread from that makes it
    easy to start a line on a thread. Although it is simple, you could
    modify it if necessary. To use it, you derive your class from it like
    this:

    Public Class TrunkThread
    Inherits ThreadWrapperBa se

    Protected Overrides Sub Execute()
    'This is where you would put the loop of execution of the
    thread
    'For example:

    Do
    'Get call to make from database or call queue
    'Make call and Deliver message if answered
    'Store results of call on call result queue or in
    database
    'Monitor line for an incoming call
    Loop Until bStopProcessing
    End Sub

    End Class

    Then to use it and start your thread, you would use code like this:

    Dim MyTrunkThread As New TrunkThread
    MyTrunkThread.S tart


    'ThreadWrapperB ase class
    Public MustInherit Class ThreadWrapperBa se

    'Our thread object
    Public ReadOnly Thread As System.Threadin g.Thread

    Public Sub New()
    'Create the thread
    Me.Thread = New System.Threadin g.Thread(Addres sOf
    Me.StartThread)
    End Sub

    'Starts execution of the thread
    Public Overridable Sub Start()
    Me.Thread.Start ()
    End Sub

    'Aborts the thread. this sub can be overridden to kill the thread
    more gracefully
    Public Overridable Sub [Stop]()
    Me.Thread.Abort ()
    End Sub

    'Property to indicate the thread is completed
    Private m_IsCompleted As Boolean
    Public ReadOnly Property IsCompleted() As Boolean
    Get
    Return m_IsCompleted
    End Get
    End Property

    'When the thread is started, this is the sub that is called, it in
    turn calls the Execute method which
    'derived classes must override.
    Private Sub StartThread()
    m_IsCompleted = False
    Execute()
    m_IsCompleted = True
    End Sub

    'This is the sub that performs the "work" of the thread. It must
    be overridden in the derived class
    Protected MustOverride Sub Execute()

    End Class

    Comment

    • Keith Mills

      #3
      Re: Threading help... threads???

      Greetings Chris!!

      Thanks for the reply...

      I simply have the thread.currentt hread.sleep(100 ) in there to basically sit
      and wait after making the callout, because we are then going to conference
      this thread / trunk with an inbound call thread.

      I had the basic threads started, all where running with application.run
      which means they would jump to the INBOUNDCALL event when the voicebocx
      received a call, I was then attempting to trigger the outbound call with a
      button on the main form (this is all for testing at this point), and this is
      where the blocking occurred.

      I then changed the main thread, so that instead of calling APPLICATION.RUN
      to startup the messaging queue, that it sat in a loop doing the following

      While True
      Thread.CurrentT hread.Sleep(100 )
      If bcallout = True Then
      RaiseEvent CallOut(iTrunk)
      End If
      if mvoicebocx.trun kstate=whatever the inboundcalling state was then
      RaiseEvent InboundCall()
      end if
      End While

      As surprisingly considering that the mvoicebocx was declared withevents the
      regular INBOUNDCALL event was never triggered... but in this loop
      methodology the trunkstate never amounts to a ringing call either.....

      Very confusing....

      "Chris Dunaway" <dunawayc@gmail .com> wrote in message
      news:1108152909 .350827.88280@l 41g2000cwc.goog legroups.com...[color=blue]
      > After a quick glance, it appears as if you have an endless loop. You
      > have these lines of code in the callout function:
      >
      > Do
      > Thread.CurrentT hread.Sleep(100 )
      > Loop
      >
      > It will never exit that loop. Secondly, you appear to be calling back
      > into the main form from the thread. This is also not a good idea, and
      > the Windows forms controls are not thread safe. At the end of this
      > post, I added a small class that you can use to create derived classes
      > that run in their own thread. The thread wrapper class just
      > encapsulates a thread and make it easy to create classes that run on
      > that thread.
      >
      > We tried using VoiceBocx with your approach but utimately decided on a
      > different approach. We wrote it so that each line basically ran in a
      > loop on a separate thread. In the loop the thread would check a "call
      > queue" to see if there were any calls to be made. If so, they would
      > remove the call record from the queue and make the call. They would
      > then store the call progress results to a separate results queue.
      > There was a single thread running that would process that queue.
      >
      > We used a single queue to service all lines on the application, but if
      > you have a small number of lines, you could have a separate queue for
      > each line, but whatever process fills the queues would have to have
      > some sort of distribution logic so that all lines would keep busy.
      >
      > Basically we had a thread that would query the database or file for the
      > phone numbers to be called. These would be placed on a call queue.
      >
      > Each vbocx line would run on its own thread in a loop until told to
      > stop. The loop would check the queue to see if there were any calls to
      > make. If so, it would grab a call from the queue and make the call and
      > deliver the message. It would then place the call progress result
      > (Busy, No Answer, etc) on a result queue. If there were no calls on
      > the queue to be made, the Vbocx thread would wait for a short time for
      > any inbound calls, it would then repeat the loop.
      >
      > There was another thread whose job was to process the items in the
      > result queue and update the database with the results.
      >
      >
      > Here is a class that you derive your TrunkThread from that makes it
      > easy to start a line on a thread. Although it is simple, you could
      > modify it if necessary. To use it, you derive your class from it like
      > this:
      >
      > Public Class TrunkThread
      > Inherits ThreadWrapperBa se
      >
      > Protected Overrides Sub Execute()
      > 'This is where you would put the loop of execution of the
      > thread
      > 'For example:
      >
      > Do
      > 'Get call to make from database or call queue
      > 'Make call and Deliver message if answered
      > 'Store results of call on call result queue or in
      > database
      > 'Monitor line for an incoming call
      > Loop Until bStopProcessing
      > End Sub
      >
      > End Class
      >
      > Then to use it and start your thread, you would use code like this:
      >
      > Dim MyTrunkThread As New TrunkThread
      > MyTrunkThread.S tart
      >
      >
      > 'ThreadWrapperB ase class
      > Public MustInherit Class ThreadWrapperBa se
      >
      > 'Our thread object
      > Public ReadOnly Thread As System.Threadin g.Thread
      >
      > Public Sub New()
      > 'Create the thread
      > Me.Thread = New System.Threadin g.Thread(Addres sOf
      > Me.StartThread)
      > End Sub
      >
      > 'Starts execution of the thread
      > Public Overridable Sub Start()
      > Me.Thread.Start ()
      > End Sub
      >
      > 'Aborts the thread. this sub can be overridden to kill the thread
      > more gracefully
      > Public Overridable Sub [Stop]()
      > Me.Thread.Abort ()
      > End Sub
      >
      > 'Property to indicate the thread is completed
      > Private m_IsCompleted As Boolean
      > Public ReadOnly Property IsCompleted() As Boolean
      > Get
      > Return m_IsCompleted
      > End Get
      > End Property
      >
      > 'When the thread is started, this is the sub that is called, it in
      > turn calls the Execute method which
      > 'derived classes must override.
      > Private Sub StartThread()
      > m_IsCompleted = False
      > Execute()
      > m_IsCompleted = True
      > End Sub
      >
      > 'This is the sub that performs the "work" of the thread. It must
      > be overridden in the derived class
      > Protected MustOverride Sub Execute()
      >
      > End Class
      >[/color]


      Comment

      • Keith Mills

        #4
        Re: Threading help... threads???

        I think we have it all figured out!!!

        Thanks CHRIS!!! That was an IMMENSE HELP!!!!!!!!!!

        Where do I send the KUDOS???

        "Chris Dunaway" <dunawayc@gmail .com> wrote in message
        news:1108152909 .350827.88280@l 41g2000cwc.goog legroups.com...[color=blue]
        > After a quick glance, it appears as if you have an endless loop. You
        > have these lines of code in the callout function:
        >
        > Do
        > Thread.CurrentT hread.Sleep(100 )
        > Loop
        >
        > It will never exit that loop. Secondly, you appear to be calling back
        > into the main form from the thread. This is also not a good idea, and
        > the Windows forms controls are not thread safe. At the end of this
        > post, I added a small class that you can use to create derived classes
        > that run in their own thread. The thread wrapper class just
        > encapsulates a thread and make it easy to create classes that run on
        > that thread.
        >
        > We tried using VoiceBocx with your approach but utimately decided on a
        > different approach. We wrote it so that each line basically ran in a
        > loop on a separate thread. In the loop the thread would check a "call
        > queue" to see if there were any calls to be made. If so, they would
        > remove the call record from the queue and make the call. They would
        > then store the call progress results to a separate results queue.
        > There was a single thread running that would process that queue.
        >
        > We used a single queue to service all lines on the application, but if
        > you have a small number of lines, you could have a separate queue for
        > each line, but whatever process fills the queues would have to have
        > some sort of distribution logic so that all lines would keep busy.
        >
        > Basically we had a thread that would query the database or file for the
        > phone numbers to be called. These would be placed on a call queue.
        >
        > Each vbocx line would run on its own thread in a loop until told to
        > stop. The loop would check the queue to see if there were any calls to
        > make. If so, it would grab a call from the queue and make the call and
        > deliver the message. It would then place the call progress result
        > (Busy, No Answer, etc) on a result queue. If there were no calls on
        > the queue to be made, the Vbocx thread would wait for a short time for
        > any inbound calls, it would then repeat the loop.
        >
        > There was another thread whose job was to process the items in the
        > result queue and update the database with the results.
        >
        >
        > Here is a class that you derive your TrunkThread from that makes it
        > easy to start a line on a thread. Although it is simple, you could
        > modify it if necessary. To use it, you derive your class from it like
        > this:
        >
        > Public Class TrunkThread
        > Inherits ThreadWrapperBa se
        >
        > Protected Overrides Sub Execute()
        > 'This is where you would put the loop of execution of the
        > thread
        > 'For example:
        >
        > Do
        > 'Get call to make from database or call queue
        > 'Make call and Deliver message if answered
        > 'Store results of call on call result queue or in
        > database
        > 'Monitor line for an incoming call
        > Loop Until bStopProcessing
        > End Sub
        >
        > End Class
        >
        > Then to use it and start your thread, you would use code like this:
        >
        > Dim MyTrunkThread As New TrunkThread
        > MyTrunkThread.S tart
        >
        >
        > 'ThreadWrapperB ase class
        > Public MustInherit Class ThreadWrapperBa se
        >
        > 'Our thread object
        > Public ReadOnly Thread As System.Threadin g.Thread
        >
        > Public Sub New()
        > 'Create the thread
        > Me.Thread = New System.Threadin g.Thread(Addres sOf
        > Me.StartThread)
        > End Sub
        >
        > 'Starts execution of the thread
        > Public Overridable Sub Start()
        > Me.Thread.Start ()
        > End Sub
        >
        > 'Aborts the thread. this sub can be overridden to kill the thread
        > more gracefully
        > Public Overridable Sub [Stop]()
        > Me.Thread.Abort ()
        > End Sub
        >
        > 'Property to indicate the thread is completed
        > Private m_IsCompleted As Boolean
        > Public ReadOnly Property IsCompleted() As Boolean
        > Get
        > Return m_IsCompleted
        > End Get
        > End Property
        >
        > 'When the thread is started, this is the sub that is called, it in
        > turn calls the Execute method which
        > 'derived classes must override.
        > Private Sub StartThread()
        > m_IsCompleted = False
        > Execute()
        > m_IsCompleted = True
        > End Sub
        >
        > 'This is the sub that performs the "work" of the thread. It must
        > be overridden in the derived class
        > Protected MustOverride Sub Execute()
        >
        > End Class
        >[/color]


        Comment

        Working...