473,890 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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
Nov 21 '05 #1
3 1533
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

Nov 21 '05 #2
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" <du******@gmail .com> wrote in message
news:11******** *************@l 41g2000cwc.goog legroups.com...
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

Nov 21 '05 #3
I think we have it all figured out!!!

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

Where do I send the KUDOS???

"Chris Dunaway" <du******@gmail .com> wrote in message
news:11******** *************@l 41g2000cwc.goog legroups.com...
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

Nov 21 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
2454
by: Andrae Muys | last post by:
Found myself needing serialised access to a shared generator from multiple threads. Came up with the following def serialise(gen): lock = threading.Lock() while 1: lock.acquire() try: next = gen.next() finally:
77
5400
by: Jon Skeet [C# MVP] | last post by:
Please excuse the cross-post - I'm pretty sure I've had interest in the article on all the groups this is posted to. I've finally managed to finish my article on multi-threading - at least for the moment. I'd be *very* grateful if people with any interest in multi-threading would read it (even just bits of it - it's somewhat long to go through the whole thing!) to check for accuracy, effectiveness of examples, etc. Feel free to mail...
0
1186
by: Stephen Barrett | last post by:
After reading through the many many many posts on threading, I still don't quite understand how to accomplish a task. Here is an overview of the app I am coding. I am sorry if it is a little long. A Windows Service app (no probs here) that basically needs to look for work to do from 1 to many MSMQ queues that it then needs to pass on to 1 to many (configurable) worker threads to process. The worker thread actually runs a few...
8
8222
by: Z D | last post by:
Hello, I'm having a strange problem that is probably due to my lack of understanding of how threading & COM Interop works in a WinForms.NET application. Here's the situation: I have a 3rd party COM component that takes about 5 seconds to run one of its functions (Network IO bound call). Since I dont want my GUI to freeze
3
5980
by: mjheitland | last post by:
Hi, I like to know how many threads are used by a Threading.Timer object. When I create a Threading.Timer object calling a short running method every 5 seconds I expected to have one additional ThreadPool thread. And that is exactly what MS VIsual Studio shows. But when I run Processexplorer or Taskmanager I see 2 additional threads, after a while another 2 additional threads. With the 3 threads at start time we have totally 7 threads.
7
318
by: Anthony Nystrom | last post by:
What is the correct way to stop a thread? abort? sleep? Will it start up again... Just curious... If the thread is enabling a form, if the form is disposed is the thread as well? Thanks, Anthony Nystrom
3
7968
by: Jayme Pechan | last post by:
I was wondering if someone could help me understand why it seems that creating threads using the code below causes handles to seemingly leak. System.Threading.Thread threadRunAsync = new System.Threading.Thread(RunFunc); threadRunAsync.Start(listParams); I have to use ThreadPools in order to avoid the handle leaks. System.Threading.ThreadPool.QueueUserWorkItem(new
0
1885
ammoos
by: ammoos | last post by:
hi friends pls help me.. i got an assignment which i feel very difficult to me.. i dont have more knowledge about multi-threading in .net... the assignment details is below.... pls help me... i have to submit this assignment today evening... please....... Windows Application to demonstrate the use of Multi-Threading with Synchronous & Asynchronous Threading. Requirements 1) A form with a) a button to initialize threads ...
5
2036
by: bean330 | last post by:
Hey, I'm somewhat new to C# and I need a little help, please! I'm selecting a bunch of records, setting properties on a COM executable and then calling a method on that executable to run. I want to run the executable in separate threads because they can be long-running and it would be optimal for us to run a bunch simultaneously. I've got that part working - it's pretty easy in C#. What I'm having a hard time with is managing the...
126
6786
by: Dann Corbit | last post by:
Rather than create a new way of doing things: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html why not just pick up ACE into the existing standard: http://www.cse.wustl.edu/~schmidt/ACE.html the same way that the STL (and subsequently BOOST) have been subsumed? Since it already runs on zillions of platforms, they have obviously worked most of the kinks out of the generalized threading and processes idea (along with many...
0
9976
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9815
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10802
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10908
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9618
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
7160
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5835
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
4259
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3267
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.