CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    May 2002
    Posts
    22

    Mutex(?) question

    I am using VB.NET and want to coordinate two threads. Each thread can write to the serial port, but I need to make sure when this happens that a single thread can complete a series of writes before the other starts (in other words, a complete and consistent block of data is written without being interpersed with data from the other thread. Should be easy using thread communications, but the documentation is pretty fuzzy. Can anyone provide a simple example where threads can mutually block each other to support this kind of communication? There appear to be several ways to do this (synclock on an object, waithandles, etc.), but the ramifications of one ver. another is not apparent. My needs should be pretty simple.

    Thanks
    Al

  2. #2
    Join Date
    Mar 2000
    Location
    Arizona, USA
    Posts
    493
    This is how I have done it in the past and it worked great.

    Private Sub WriteToSerialPort(ByVal Data() As Byte)
    Dim CurrThread As Thread

    '//Get A Reference To The Calling Thread
    CurrThread = Thread.CurrentThread

    '//Block All Other Calling Threads
    SyncLock CurrThread
    '//Write To Serial Port And What Ever Else That Needs Done
    End SyncLock

    End Sub
    Kris
    Software Engineer
    Phoenix, AZ USA

  3. #3
    Join Date
    May 2002
    Posts
    22
    Kris-

    Thanks for the suggestion. I built a little ap to test your approach and discovered it doesn't work quite right (I think???). I believe there's a problem with locking on an object within a procedure called from multiple threads. Each thread will use a new call to the procedure which will create a new instance of the lock object. The result is no lock at all! To fix this, move the lock object up to higher-level scope.

    I was having so much fun with this, I wanted to share the little ap I made if anyone else wants to play with threading/mutex. Notice that I also used a simpler object for the synclock. I think any object at all will do, so I picked a simpler one than you used. Do you think it matters?

    The attached file is a small ap that show how to create new threads and how to lock access to a section of code to ensure that only a single thread at a time can execute the code. I also illustrated a few other principles like thread priority and inter-task signalling.

    I did run across a problem with the debugger. If I break on the sub OneAtATime and try to single step into it, the debuger will NOT step past the synclock. It just hangs there. Anyone else see this??

    Kris-I left your suggested way in but commented it out in case you want to try it. I'm new to .NET threading, so any comments are welcome!!!

    Cheers
    Al

  4. #4
    Join Date
    May 2002
    Posts
    22
    I tried to "attach" code to the prior message, but it doesn't seem to work. Why is .VB not a valid file extension. Anyway, here it is the kludgy way (I'll figure out how to do it right next time):

    Option Strict On
    Option Explicit On
    Imports System.Threading

    Public Class Test
    Inherits System.Windows.Forms.Form
    Private Lock(0) As Integer 'Has to be a reference type for SyncLock
    Private Released As Boolean
    Private T1AREvent As New AutoResetEvent(False)
    Private T2AREvent As New AutoResetEvent(False)
    Private Thread1 As Thread
    Private Thread2 As Thread


    #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 TName As System.Windows.Forms.TextBox
    Friend WithEvents Launch1 As System.Windows.Forms.Button
    Friend WithEvents Launch2 As System.Windows.Forms.Button
    Friend WithEvents Release As System.Windows.Forms.Button
    Friend WithEvents Both As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    Me.TName = New System.Windows.Forms.TextBox()
    Me.Launch1 = New System.Windows.Forms.Button()
    Me.Launch2 = New System.Windows.Forms.Button()
    Me.Release = New System.Windows.Forms.Button()
    Me.Both = New System.Windows.Forms.Button()
    Me.SuspendLayout()
    '
    'TName
    '
    Me.TName.Location = New System.Drawing.Point(24, 16)
    Me.TName.Name = "TName"
    Me.TName.Size = New System.Drawing.Size(64, 20)
    Me.TName.TabIndex = 0
    Me.TName.Text = ""
    '
    'Launch1
    '
    Me.Launch1.Location = New System.Drawing.Point(24, 56)
    Me.Launch1.Name = "Launch1"
    Me.Launch1.Size = New System.Drawing.Size(64, 23)
    Me.Launch1.TabIndex = 1
    Me.Launch1.Text = "Launch1"
    '
    'Launch2
    '
    Me.Launch2.Location = New System.Drawing.Point(24, 88)
    Me.Launch2.Name = "Launch2"
    Me.Launch2.Size = New System.Drawing.Size(64, 23)
    Me.Launch2.TabIndex = 2
    Me.Launch2.Text = "Launch2"
    '
    'Release
    '
    Me.Release.Location = New System.Drawing.Point(24, 152)
    Me.Release.Name = "Release"
    Me.Release.Size = New System.Drawing.Size(64, 23)
    Me.Release.TabIndex = 3
    Me.Release.Text = "Release"
    '
    'Both
    '
    Me.Both.Location = New System.Drawing.Point(25, 120)
    Me.Both.Name = "Both"
    Me.Both.Size = New System.Drawing.Size(64, 23)
    Me.Both.TabIndex = 4
    Me.Both.Text = "Both"
    '
    'Test
    '
    Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
    Me.ClientSize = New System.Drawing.Size(115, 198)
    Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.Both, Me.Release, Me.Launch2, Me.Launch1, Me.TName})
    Me.Name = "Test"
    Me.ResumeLayout(False)

    End Sub

    #End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Thread1 = New Thread(New ThreadStart(AddressOf Task1))
    Thread1.Name = "Task1"
    Thread1.Priority = ThreadPriority.Highest
    Thread1.IsBackground = True 'Set to background so it's automatically killed.
    Thread2 = New Thread(New ThreadStart(AddressOf Task2))
    Thread2.Name = "Task2"
    Thread2.Priority = ThreadPriority.Lowest
    Thread2.IsBackground = True 'Set to background so it's automatically killed.
    Thread.CurrentThread.Name = "Default VB Thread" 'So it's easy to spot in Thread debug window
    Released = False
    TName.Text = ""

    Thread1.Start()
    Thread2.Start()
    End Sub

    Private Sub Task1()
    While (True)
    'T1AREvent.Reset()
    T1AREvent.WaitOne()
    OneAtATime()
    End While
    End Sub

    Private Sub Task2()
    While (True)
    'T2AREvent.Reset()
    T2AREvent.WaitOne()
    OneAtATime()
    End While
    End Sub

    Private Sub OneAtATime()
    ''''Dim CurrThread As Thread

    ''''CurrThread = Thread.CurrentThread 'Get A Reference To The Calling Thread
    ''''SyncLock CurrThread 'Block All Other Calling Threads
    SyncLock Lock
    'Critical section follows
    TName.Text = Thread.CurrentThread.Name
    While Not Released
    Thread.CurrentThread.Sleep(50) 'Wait 50mSec
    End While
    TName.Text = ""
    Released = False
    End SyncLock
    End Sub

    Private Sub Launch1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Launch1.Click
    T1AREvent.Set() 'Kick off Task1
    End Sub

    Private Sub Launch2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Launch2.Click
    T2AREvent.Set() 'Kick off Task2
    End Sub

    Private Sub Both_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Both.Click
    If Int(DateAndTime.Timer) Mod 2 = 1 Then 'A pseudorandomizer
    T1AREvent.Set() 'Kick off Task1
    T2AREvent.Set() 'Kick off Task2
    Else
    T2AREvent.Set() 'Kick off Task2
    T1AREvent.Set() 'Kick off Task1
    End If
    End Sub

    Private Sub Release_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Release.Click
    Released = True
    End Sub
    End Class

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured