Do you occasionally need multithreaded timed-out operations? Let me say, this is a very basic implementation, but is the best solution for trying many different methods for completing your operation before you choose the best one, and it lets you start from a small basic (but so easy to get) multithreaded stuff that you can grow or change as much as you like since this class is released under GNU LGPL compatible license (means I don't care anything).
I will refer to the example of a DNS resolving operation (scanner), but it can be any multithreaded timed-out operation.
Question: what should "atomically" do our operation? Here is an example (DNS resolving example, it's easy to write the atomic job):
Private Function MyJob(IP as Object)As Object
Dim IPString as String = IP
Now I want this to be multithreaded and don't want to wait for the DNS for more than 3 sec per thread.
This is where the class comes in handy.
To use the class, simply create a MOP
Dim WithEvents MOP as MultiThreadedTimedOutOperation
MOP by giving a reference to our atomic job function, and optionally, the maximum number of threads and the timeout.
MOP = New MultiThreadedTimedOutOperation(AddressOf MyJob,40,3000)
I want to scan my entire subnet. Imagine that, we have our subnet prefix stored in
String) as ("1.2.3."), so add the 254 jobs just like this:
Dim I as integer
For I = 1 to 254
MOP.QueueJob(LocalSNPrefix + I.ToString)
Now I want to start my operation:
Now I can have implemented (not necessary) a function to catch
performstepevent (to use with the progress bar). Anyway, you need to know when the operation is finished and of course get the results.
Private Sub OnOpFinish()Handles MOP.OpFinished
Dim S as Stack = MOP.GetResults()
Dim I as Integer
For I = 1 to S.count
Dim Result as string = S.Pop
If Not Result.Equals("NotResolved")
MessageBox.Show("ResolvedIP :" + Result)
That's it. Anyway I don't suggest this class be used in any "release version" without "strong implementation" stuff like late binding objects, and often there would be no need to make sure that an atomic operation has finished if it is placed into a separate thread as the class does. In fact, often you will already have a function that supports timing out by its own.
And if you think you can do better, don't wait.
Here's the code, copy and paste it directly into your VB.NET project or download the file from the zip file.
Public Class MultiThreadedTimedOutOperation
Public Delegate Function Job(ByVal InitState As Object) As Object
Public Event PerformStep()
Public Event OpFinished()
Private JobStart As Job
Private Results As New Stack
Private TS As New Queue
Private ActiveThreads As Integer
Private ReadOnly MaxThreads As Integer = 40
Private ReadOnly Waittime As Integer = 3000
Public Sub New(ByVal Method As Job, Optional ByVal maxthreads _
As Integer = 40, Optional ByVal Timeout As Integer = 3000)
Me.MaxThreads = maxthreads
Me.Waittime = Timeout
JobStart = Method
Public Sub QueueJob(ByVal UserJobStartState As Object)
Public Sub StartOperation()
Dim t As New Threading.Thread(AddressOf MainJob)
t.ApartmentState = Threading.ApartmentState.MTA
Public Function GetResults() As Stack
Private Sub MainJob()
While TS.Count > 0
If ActiveThreads < MaxThreads Then
System.Threading.Thread.Sleep(Waittime / MaxThreads)
Private Sub Do1Job()
Dim t As New Threading.Thread(AddressOf TimingOutJob)
Private Sub TimingOutJob()
ActiveThreads += 1
Dim t As New Threading.Thread(AddressOf JobInvoke)
If Not t.Join(Waittime) Then t.Abort()
ActiveThreads -= 1
Private Sub JobInvoke()
Dim ThisJob As String = TS.Dequeue
Dim Result As Object = JobStart.Invoke(ThisJob, Nothing, Nothing)
If Not Result Is Nothing Then Results.Push(Result)