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
    Friend WithEvents cmdStart As System.Windows.Forms.Button

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

    '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 chkSynclock As System.Windows.Forms.CheckBox
    Friend WithEvents GroupBox1 As System.Windows.Forms.GroupBox
    Friend WithEvents Label3 As System.Windows.Forms.Label
    Friend WithEvents Label2 As System.Windows.Forms.Label
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents lblGlobal As System.Windows.Forms.Label
    Friend WithEvents lblThread2 As System.Windows.Forms.Label
    Friend WithEvents lblThread1 As System.Windows.Forms.Label
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.cmdStart = New System.Windows.Forms.Button()
        Me.chkSynclock = New System.Windows.Forms.CheckBox()
        Me.GroupBox1 = New System.Windows.Forms.GroupBox()
        Me.Label3 = New System.Windows.Forms.Label()
        Me.Label2 = New System.Windows.Forms.Label()
        Me.Label1 = New System.Windows.Forms.Label()
        Me.lblGlobal = New System.Windows.Forms.Label()
        Me.lblThread2 = New System.Windows.Forms.Label()
        Me.lblThread1 = New System.Windows.Forms.Label()
        Me.GroupBox1.SuspendLayout()
        Me.SuspendLayout()
        '
        'cmdStart
        '
        Me.cmdStart.Location = New System.Drawing.Point(76, 156)
        Me.cmdStart.Name = "cmdStart"
        Me.cmdStart.Size = New System.Drawing.Size(104, 32)
        Me.cmdStart.TabIndex = 2
        Me.cmdStart.Text = "Start"
        '
        'chkSynclock
        '
        Me.chkSynclock.Location = New System.Drawing.Point(12, 132)
        Me.chkSynclock.Name = "chkSynclock"
        Me.chkSynclock.Size = New System.Drawing.Size(220, 16)
        Me.chkSynclock.TabIndex = 4
        Me.chkSynclock.Text = "Use SyncLock"
        '
        'GroupBox1
        '
        Me.GroupBox1.Controls.AddRange(New System.Windows.Forms.Control() {Me.Label3, Me.Label2, Me.Label1, Me.lblGlobal, Me.lblThread2, Me.lblThread1})
        Me.GroupBox1.Location = New System.Drawing.Point(8, 8)
        Me.GroupBox1.Name = "GroupBox1"
        Me.GroupBox1.Size = New System.Drawing.Size(236, 112)
        Me.GroupBox1.TabIndex = 5
        Me.GroupBox1.TabStop = False
        '
        'Label3
        '
        Me.Label3.Location = New System.Drawing.Point(16, 80)
        Me.Label3.Name = "Label3"
        Me.Label3.Size = New System.Drawing.Size(96, 20)
        Me.Label3.TabIndex = 13
        Me.Label3.Text = "Global Counter:"
        '
        'Label2
        '
        Me.Label2.Location = New System.Drawing.Point(16, 44)
        Me.Label2.Name = "Label2"
        Me.Label2.Size = New System.Drawing.Size(96, 20)
        Me.Label2.TabIndex = 12
        Me.Label2.Text = "Thread 2:"
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(16, 20)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(96, 20)
        Me.Label1.TabIndex = 11
        Me.Label1.Text = "Thread 1:"
        '
        'lblGlobal
        '
        Me.lblGlobal.Location = New System.Drawing.Point(124, 80)
        Me.lblGlobal.Name = "lblGlobal"
        Me.lblGlobal.Size = New System.Drawing.Size(96, 16)
        Me.lblGlobal.TabIndex = 10
        '
        'lblThread2
        '
        Me.lblThread2.Location = New System.Drawing.Point(124, 44)
        Me.lblThread2.Name = "lblThread2"
        Me.lblThread2.Size = New System.Drawing.Size(96, 20)
        Me.lblThread2.TabIndex = 9
        '
        'lblThread1
        '
        Me.lblThread1.Location = New System.Drawing.Point(124, 20)
        Me.lblThread1.Name = "lblThread1"
        Me.lblThread1.Size = New System.Drawing.Size(96, 20)
        Me.lblThread1.TabIndex = 8
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 14)
        Me.ClientSize = New System.Drawing.Size(252, 198)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.GroupBox1, Me.chkSynclock, Me.cmdStart})
        Me.Font = New System.Drawing.Font("Tahoma", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Name = "Form1"
        Me.Text = "Synchronization Tester"
        Me.GroupBox1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Public MyGlobalCounter As New GlobalCounter()

    Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStart.Click
        MyGlobalCounter.Counter = 0

        Dim IncrementThread1 As New IncrementThread(MyGlobalCounter, lblThread1, lblGlobal, chkSynclock.Checked)
        Dim IncrementThread2 As New IncrementThread(MyGlobalCounter, lblThread2, lblGlobal, chkSynclock.Checked)
        Dim MyThread1 As New Thread(AddressOf IncrementThread1.Increment)
        Dim MyThread2 As New Thread(AddressOf IncrementThread2.Increment)
        MyThread1.Start()
        MyThread2.Start()

    End Sub


End Class

Public Class GlobalCounter
    Public Counter As Integer
End Class



Public Delegate Sub CallBackFunction(ByVal Counter As Integer)

Public Class IncrementThread

    Private Counter As GlobalCounter
    Private LocalCounter As Integer
    Private ThreadLabel, GlobalLabel As Label
    Private EnableSyncLock As Boolean

    Public Sub New(ByVal Counter As GlobalCounter, ByVal ThreadLabel As Label, ByVal GlobalLabel As Label, ByVal EnableSyncLock As Boolean)
        Me.Counter = Counter
        Me.ThreadLabel = ThreadLabel
        Me.GlobalLabel = GlobalLabel
        Me.EnableSyncLock = EnableSyncLock
    End Sub

    Public Sub Increment()

        Dim i As Integer
        Dim GlobalCounter As Integer

        For i = 1 To 1000
            LocalCounter = LocalCounter + 1
            If EnableSyncLock = True Then
                SyncLock Counter
                    GlobalCounter = Counter.Counter
                    Thread.Sleep(TimeSpan.FromTicks(1))
                    Counter.Counter = GlobalCounter + 1
                End SyncLock
            Else
                GlobalCounter = Counter.Counter
                Thread.Sleep(TimeSpan.FromTicks(1))
                Counter.Counter = GlobalCounter + 1
            End If
        Next i

        Dim Invoker As New MethodInvoker(AddressOf UpdateLabel)

        ' Assume that ThreadLabel and GlobalLabel are on the same window.
        ThreadLabel.Invoke(Invoker)

    End Sub

    Private Sub UpdateLabel()
        ThreadLabel.Text = LocalCounter.ToString()
        GlobalLabel.Text = Counter.Counter.ToString()
    End Sub

End Class