Multithread Stop/Restart

J

juky

Hi all,

I have 3 running threads chencking for something in my application.
Based on that I need to stop some of them safely wait for something
else and restart. Sleep is not good in my case because i don't know how
much to wait. How and from where I can put a thread in pause an restart
it?

Thank you
Juky


Sub main ()
....
t1 = New Threading.Thread(AddressOf Check1)
t1.Start()
t2 = New Threading.Thread(AddressOf Check2)
t2.Start()
t3 = New Threading.Thread(AddressOf Check3)
t3.Start()
end sub

sub Check1()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub

sub Check2()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub

sub Check3()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub
 
C

Cor Ligthert

Juky,

Are you sure you need those threads.

Remember that the processing time of an applications with multithreading is
longer than withouth that.

When there are a lot of dependencies that can be as well for the throughput
time.

Cor
 
S

Stephany Young

One way to do it is to have an appropriately scoped boolean variable (check)
and set/reset it as required in your external code. In you thread(s), handle
the condition thus:

Sub Check1()

Do

If Not check Then

' Do whatever needs doing

End If

Loop

End Sub

Whatever processing the thread does will effectively be suspended while
check it set.
Note that if check is set while the thread is actually doing it's processing
then the 'suspension' will not be effective until the next iteration of the
loop, but this should give you the general idea.
 
H

Herfried K. Wagner [MVP]

juky said:
I have 3 running threads chencking for something in my application.
Based on that I need to stop some of them safely wait for something
else and restart. Sleep is not good in my case because i don't know how
much to wait. How and from where I can put a thread in pause an restart
it?

The sample below will start a thread that waits (blocks the thread) until an
event occurs:

\\\
Imports System.Threading

Public Module Program
Private SampleTest As New Test()

Public Sub Main()
Dim t As New Thread(AddressOf SampleTest.Foo)
t.Start()
Console.ReadLine()
SampleTest.EventHandler()
End Sub
End Module

Public Class Test
Private EventOccured As New ManualResetEvent(False)

Public Sub Foo()
Debug.WriteLine("Started!")
EventOccured.WaitOne(-1, False)
Debug.WriteLine("Event occured!")
End Sub

Public Sub EventHandler()
EventOccured.Set()
End Sub
End Class
///
 
J

Jay B. Harlow [MVP - Outlook]

Juky,
As Herfried suggests I would use a ManualResetEvent.

Here is a an example I posted a few weeks ago of a Worker class using a
ManualResetEvent to control suspending & resuming.

Public Class Worker

Public Delegate Sub Work()

Private ReadOnly m_work As Work
Private ReadOnly m_arg As Object
Private ReadOnly m_event As ManualResetEvent
Private ReadOnly m_thread As Thread

<ThreadStatic()> _
Private Shared m_current As Worker

Public Sub New(ByVal work As Work, ByVal arg As Object, ByVal name
As String)
m_work = work
m_arg = arg
m_event = New ManualResetEvent(True)
m_thread = New Thread(AddressOf Start)
m_thread.Name = name
m_thread.IsBackground = True
m_thread.Start()
End Sub

Private Sub Start()
m_current = Me
m_work.Invoke()
End Sub

Public Shared ReadOnly Property CurrentWorker() As Worker
Get
Return m_current
End Get
End Property

Public ReadOnly Property Arg() As Object
Get
Return m_arg
End Get
End Property

Public ReadOnly Property Name() As String
Get
Return m_thread.Name
End Get
End Property

Public Sub Suspend()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("Suspend should not be
called from the worker thread!")
End If
m_event.Reset()
End Sub

Public Sub [Resume]()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("Resume should not be
called from the worker thread!")
End If
m_event.Set()
End Sub

Public Sub WaitForTermination()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("WaitForTermination
should not be called from the worker thread!")
End If
m_thread.Join()
End Sub

Public Sub CheckSuspend()
If Not Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("CheckSuspend should
only be called from the worker thread!")
End If
m_event.WaitOne()
End Sub

End Class



To see how it works try something like:

Private Sub Work()
For index As Integer = 1 To 50
Worker.CurrentWorker.CheckSuspend()
Debug.WriteLine(index, Worker.CurrentWorker.Name)
Dim value As Double = DirectCast(Worker.CurrentWorker.Arg,
Double)
Thread.Sleep(TimeSpan.FromSeconds(value))
Next
End Sub

Public Sub Main()
Dim worker1 As New Worker(AddressOf Work, 0.25, "worker1")
Dim worker2 As New Worker(AddressOf Work, 0.5, "worker2")
Dim worker3 As New Worker(AddressOf Work, 0.75, "worker3")

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker1.Suspend()

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker2.Suspend()

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker3.Suspend()

Debug.WriteLine("Pausing 1 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(1))

worker1.Resume()
worker2.Resume()
worker3.Resume()

Debug.WriteLine("Waiting for Termination", "Main")
worker1.WaitForTermination()
worker2.WaitForTermination()
worker3.WaitForTermination()

End Sub

The above sample was posted in a thread titled "Technique for Pausing Worker
Thread" in this newsgroup between 21 Jan 2005 & 23 Jan 2005.

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

I missed an addendum to the original thread:

An alternate Worker.Suspend implementation might be:

Public Sub Suspend()
m_event.Reset()
If Thread.CurrentThread Is m_thread Then
m_event.WaitOne()
End If
End Sub

Which allows the worker thread to suspend itself.

I would also consider implementing CurrentWorker as:

Public Shared ReadOnly Property CurrentWorker() As Worker
Get
If m_current Is Nothing Then
Throw New InvalidOperationException("CurrentWorker
should only be called from a Worker thread!")
End If
Return m_current
End Get
End Property

To ensure that it is only called from Worker Threads (preventing
NullReferenceExceptions in non-worker threads!).

Hope this helps
Jay


Jay B. Harlow said:
Juky,
As Herfried suggests I would use a ManualResetEvent.

Here is a an example I posted a few weeks ago of a Worker class using a
ManualResetEvent to control suspending & resuming.

Public Class Worker

Public Delegate Sub Work()

Private ReadOnly m_work As Work
Private ReadOnly m_arg As Object
Private ReadOnly m_event As ManualResetEvent
Private ReadOnly m_thread As Thread

<ThreadStatic()> _
Private Shared m_current As Worker

Public Sub New(ByVal work As Work, ByVal arg As Object, ByVal name
As String)
m_work = work
m_arg = arg
m_event = New ManualResetEvent(True)
m_thread = New Thread(AddressOf Start)
m_thread.Name = name
m_thread.IsBackground = True
m_thread.Start()
End Sub

Private Sub Start()
m_current = Me
m_work.Invoke()
End Sub

Public Shared ReadOnly Property CurrentWorker() As Worker
Get
Return m_current
End Get
End Property

Public ReadOnly Property Arg() As Object
Get
Return m_arg
End Get
End Property

Public ReadOnly Property Name() As String
Get
Return m_thread.Name
End Get
End Property

Public Sub Suspend()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("Suspend should not be
called from the worker thread!")
End If
m_event.Reset()
End Sub

Public Sub [Resume]()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("Resume should not be
called from the worker thread!")
End If
m_event.Set()
End Sub

Public Sub WaitForTermination()
If Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("WaitForTermination
should not be called from the worker thread!")
End If
m_thread.Join()
End Sub

Public Sub CheckSuspend()
If Not Thread.CurrentThread Is m_thread Then
Throw New InvalidOperationException("CheckSuspend should
only be called from the worker thread!")
End If
m_event.WaitOne()
End Sub

End Class



To see how it works try something like:

Private Sub Work()
For index As Integer = 1 To 50
Worker.CurrentWorker.CheckSuspend()
Debug.WriteLine(index, Worker.CurrentWorker.Name)
Dim value As Double = DirectCast(Worker.CurrentWorker.Arg,
Double)
Thread.Sleep(TimeSpan.FromSeconds(value))
Next
End Sub

Public Sub Main()
Dim worker1 As New Worker(AddressOf Work, 0.25, "worker1")
Dim worker2 As New Worker(AddressOf Work, 0.5, "worker2")
Dim worker3 As New Worker(AddressOf Work, 0.75, "worker3")

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker1.Suspend()

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker2.Suspend()

Debug.WriteLine("Pausing 5 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(5))
worker3.Suspend()

Debug.WriteLine("Pausing 1 seconds", "Main")
Thread.Sleep(TimeSpan.FromSeconds(1))

worker1.Resume()
worker2.Resume()
worker3.Resume()

Debug.WriteLine("Waiting for Termination", "Main")
worker1.WaitForTermination()
worker2.WaitForTermination()
worker3.WaitForTermination()

End Sub

The above sample was posted in a thread titled "Technique for Pausing
Worker Thread" in this newsgroup between 21 Jan 2005 & 23 Jan 2005.

Hope this helps
Jay


juky said:
Hi all,

I have 3 running threads chencking for something in my application.
Based on that I need to stop some of them safely wait for something
else and restart. Sleep is not good in my case because i don't know how
much to wait. How and from where I can put a thread in pause an restart
it?

Thank you
Juky


Sub main ()
....
t1 = New Threading.Thread(AddressOf Check1)
t1.Start()
t2 = New Threading.Thread(AddressOf Check2)
t2.Start()
t3 = New Threading.Thread(AddressOf Check3)
t3.Start()
end sub

sub Check1()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub

sub Check2()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub

sub Check3()
while true
"IF CHECK=TRUE THEN I HAVET TO SUSPEND THIS THREAD
end while
end Sub
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top