473,385 Members | 1,834 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Thread Safe/Synchronized Queue question

I am working on a generic way to launch multiple similar processes (threads)
at once, but limit the number of threads running at any one time to a number
I set. As I understand it the following line makes a Queue "thread safe", so
I do not need to explicitly lock and unlock it when multiple threads are
working with it.

'Thread safe queue
Private IndexQueue As Queue = Queue.Synchronized(New Queue)
The following code seems to demonstrate this point quite well. However,
there is one oddity I do not understand. I have to introduce a delay
(Thread.CurrentThread.Sleep(5)) after launching each thread or else I get an
error that the queue is empty when I try to dequeue the next item. This 5 ms
delay is no big deal in this example, however I have found that if I am
doing actual work I have had to increase this value to 300, 500 or even 1000
to avoid the error.

Can anyone tell me what is going on?
Dave Coate
Option Strict On

Imports System.Threading

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() 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.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'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 lblThreadCount As System.Windows.Forms.Label
Friend WithEvents lblTotal As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents lblFinished As System.Windows.Forms.Label
Friend WithEvents btnGo As System.Windows.Forms.Button
Friend WithEvents dgMailboxes As System.Windows.Forms.DataGrid
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.lblThreadCount = New System.Windows.Forms.Label
Me.lblTotal = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.lblFinished = New System.Windows.Forms.Label
Me.btnGo = New System.Windows.Forms.Button
Me.dgMailboxes = New System.Windows.Forms.DataGrid
CType(Me.dgMailboxes,
System.ComponentModel.ISupportInitialize).BeginIni t()
Me.SuspendLayout()
'
'lblThreadCount
'
Me.lblThreadCount.Anchor =
CType((System.Windows.Forms.AnchorStyles.Bottom Or
System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
Me.lblThreadCount.Location = New System.Drawing.Point(8, 347)
Me.lblThreadCount.Name = "lblThreadCount"
Me.lblThreadCount.TabIndex = 11
Me.lblThreadCount.Text = "0"
'
'lblTotal
'
Me.lblTotal.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom
Or System.Windows.Forms.AnchorStyles.Right),
System.Windows.Forms.AnchorStyles)
Me.lblTotal.Location = New System.Drawing.Point(280, 347)
Me.lblTotal.Name = "lblTotal"
Me.lblTotal.Size = New System.Drawing.Size(48, 23)
Me.lblTotal.TabIndex = 10
Me.lblTotal.Text = "0"
'
'Label2
'
Me.Label2.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom
Or System.Windows.Forms.AnchorStyles.Right),
System.Windows.Forms.AnchorStyles)
Me.Label2.Location = New System.Drawing.Point(240, 347)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(24, 23)
Me.Label2.TabIndex = 9
Me.Label2.Text = "Of"
'
'lblFinished
'
Me.lblFinished.Anchor =
CType((System.Windows.Forms.AnchorStyles.Bottom Or
System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.lblFinished.Location = New System.Drawing.Point(192, 347)
Me.lblFinished.Name = "lblFinished"
Me.lblFinished.Size = New System.Drawing.Size(32, 23)
Me.lblFinished.TabIndex = 8
Me.lblFinished.Text = "0"
'
'btnGo
'
Me.btnGo.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or
System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.btnGo.Location = New System.Drawing.Point(336, 347)
Me.btnGo.Name = "btnGo"
Me.btnGo.TabIndex = 7
Me.btnGo.Text = "Go"
'
'dgMailboxes
'
Me.dgMailboxes.Anchor =
CType((((System.Windows.Forms.AnchorStyles.Top Or
System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right),
System.Windows.Forms.AnchorStyles)
Me.dgMailboxes.DataMember = ""
Me.dgMailboxes.HeaderForeColor =
System.Drawing.SystemColors.ControlText
Me.dgMailboxes.Location = New System.Drawing.Point(0, 3)
Me.dgMailboxes.Name = "dgMailboxes"
Me.dgMailboxes.Size = New System.Drawing.Size(416, 328)
Me.dgMailboxes.TabIndex = 6
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(416, 373)
Me.Controls.Add(Me.lblThreadCount)
Me.Controls.Add(Me.lblTotal)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.lblFinished)
Me.Controls.Add(Me.btnGo)
Me.Controls.Add(Me.dgMailboxes)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.dgMailboxes,
System.ComponentModel.ISupportInitialize).EndInit( )
Me.ResumeLayout(False)

End Sub

#End Region

Private m_dt As DataTable
Private LastIndex As Integer
Private IndexQueue As Queue = Queue.Synchronized(New Queue)
Private m_CurrentRowIndex As Integer
Private ThreadCount As Integer
Private FinishedCount As Integer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Create and show a datatable of items to be processed and track
progress
m_dt = New DataTable
m_dt.Columns.Add("Index")
m_dt.Columns.Add("Delay")
m_dt.Columns.Add("ThreadState")
m_dt.Columns.Add("Result")

For ix As Integer = 0 To 10
Dim NewRow As DataRow = m_dt.NewRow
With NewRow
.Item("Index") = ix
.Item("Delay") = CInt(Rnd(ix) * 10000)
End With
m_dt.Rows.Add(NewRow)
Next

dgMailboxes.DataSource = m_dt
End Sub

Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnGo.Click
LastIndex = m_dt.Rows.Count - 1
lblTotal.Text = CStr(LastIndex + 1)

'Fill a queue of items (index to table) to process
For m_CurrentRowIndex = 0 To LastIndex
IndexQueue.Enqueue(m_CurrentRowIndex)
Next

'Process items in the queue
While IndexQueue.Count > 0
lblThreadCount.Text = CStr(ThreadCount)
lblThreadCount.Refresh()

'Launch a new thread if there are less than 20 threads running
If ThreadCount < 20 Then
Dim t As New Thread(AddressOf RunDummyTask)
t.IsBackground = False
t.Start()
End If

'Refresh Gui objects
dgMailboxes.Refresh()
lblTotal.Refresh()
lblThreadCount.Refresh()
'needed while threads are starting
lblFinished.Text = CStr(FinishedCount)
lblFinished.Refresh()

'Program crashes without this line. Why?
'Error: Queue Empty
Thread.CurrentThread.Sleep(5)

End While
End Sub

Private Sub RunDummyTask()
'Increment thread count
ThreadCount += 1

'Dequeue the next index
Dim Index As Integer = CInt(IndexQueue.Dequeue)

'Get data about the process to run
Dim Delay As Integer = CInt(m_dt.Rows(Index)("Delay"))

'Show progress of the thread in the GUI
m_dt.Rows(Index)("ThreadState") = "Started"

'Run Process
Thread.CurrentThread.Sleep(Delay)

'Show progress of the thread in the GUI
m_dt.Rows(Index)("Result") = "Completed"

'Decrement the thread count
ThreadCount -= 1

'track progress in GUI
FinishedCount += 1
'needed after all threads have started
lblFinished.Text = CStr(FinishedCount)

'If this is the last thread...
If FinishedCount = LastIndex + 1 Then
Done()
End If

End Sub

Private Sub Done()
MsgBox("Done")
End Sub

End Class

Nov 21 '05 #1
0 1603

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

Similar topics

7
by: sayoyo | last post by:
Hi, Is there some way that we can reuse a thread by replacing the runnable object of the thread? like a thread is not "alive" anymore, then we remove the runnable object(is it possible????) and...
0
by: Chris Stransky | last post by:
What is the easiest way to create a thread safe ListView Control ... e.g. use you own wrapper ... use a thread safe queue ... etc. There is no Synchronized or SyncRoot method available to get a...
1
by: Frank Rizzo | last post by:
Some of the classes in the framework are marked as thread-safe in the documentation. In particular the docs say the following: "Any public static (*Shared* in Visual Basic) members of this type...
5
by: Cyrus | last post by:
I have a question regarding synchronization across multiple threads for a Hashtable. Currently I have a Threadpool that is creating worker threads based on requests to read/write to a hashtable....
2
by: Shane Story | last post by:
The Collections.Queue class has a Synchronized property. My colleague was saying that this means that we can use the queue in a multi-threaded app and not worry about normal threading issues. ...
6
by: fniles | last post by:
I am using VB.NET 2003 and a socket control to receive and sending data to clients. As I receive data in 1 thread, I put it into an arraylist, and then I remove the data from arraylist and send it...
9
by: cgwalters | last post by:
Hi, I've recently been working on an application which does quite a bit of searching through large data structures and string matching, and I was thinking that it would help to put some of this...
7
by: Boki | last post by:
Multi-thread read/write to a single file. I have two processing threads, thread A and thread B; and I called my queue as Q. Thread A will feed data into Q by user input, the timing is random....
29
by: NvrBst | last post by:
I've read a bit online seeing that two writes are not safe, which I understand, but would 1 thread push()'ing and 1 thread pop()'ing be thread-safe? Basically my situation is the follows: ...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...

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.