troubleshooting Question

Help I dont understand multithreading&&&&&. Cross Thread Calls error

Avatar of Ajfy2k
Ajfy2k asked on
Visual Basic.NETMicrosoft DevelopmentEditors IDEs
9 Comments1 Solution1647 ViewsLast Modified:
Hi recently upgraded my app to vs2008 for vs2003, I have a progress window that runs on s separate thread when the application accesses the database that now gets the Cross Thread Calls error so I have to .CheckForIllegalCrossThreadCalls = False, I would rather fix the error than ignore it. I believe I need to use invoke? But cant quite figure out where and how,

Code that starts of the progress window  no errors

Public Module modMain

    Dim ThreadSpinningProgress As System.Threading.Thread
    Dim SpinningProgress As DTEControls.SpinningProgress

    Public Sub StartSpinningProgressWatch()
        Try

            SpinningProgress = New DTEControls.SpinningProgress
            ThreadSpinningProgress = New System.Threading.Thread(AddressOf SpinningProgress.Show)
            ThreadSpinningProgress.Start()

        Catch ex As Exception
            LogError(ex)
        End Try
    End Sub
End Module

Code that errors, errors on refresh "Cross-thread operation not valid: Control 'SpinningProgress' accessed from a thread other than the thread it was created on."
See code snippet for full class

Private Sub IncrementTransisionSegment(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
        Try

        If m_TransitionSegment = 11 Then
            m_TransitionSegment = 0
            m_BehindIsActive = Not m_BehindIsActive
        ElseIf m_TransitionSegment = -1 Then
            m_TransitionSegment = 0
        Else
            m_TransitionSegment += 1
        End If

            Invalidate()
            Me.Refresh()

        Catch ex As Exception
            MsgBox("Spinning Progress error traped; " & ex.Message, MsgBoxStyle.OkOnly)
        End Try
    End Sub

Hope you can help

Friend Class SpinningProgress
    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
        CalculateSegments()
 
        m_AutoRotateTimer = New System.Timers.Timer(m_IncrementFrequency)
        AddHandler m_AutoRotateTimer.Elapsed, AddressOf IncrementTransisionSegment
        m_AutoRotateTimer.Start()
 
        'Temp fix to avoid error, we need to sort out bad code not use this property
        'Control.CheckForIllegalCrossThreadCalls = True
    End Sub
 
    'UserControl 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.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        '
        'SpinningProgress
        '
        Me.AutoScaleMode = Windows.Forms.AutoScaleMode.None
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.BackColor = System.Drawing.Color.FromArgb(CType(247, Byte), CType(146, Byte), CType(39, Byte))
        Me.ClientSize = New System.Drawing.Size(98, 103)
        Me.ControlBox = False
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
        Me.Name = "SpinningProgress"
        Me.ShowInTaskbar = False
        Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
        Me.TopMost = True
 
    End Sub
 
#End Region
    Private m_InactiveColour As Color = Color.FromArgb(247, 146, 39)
    Private m_ActiveColour As Color = Color.FromArgb(66, 120, 67)
    Private m_TransistionColour As Color = Color.FromArgb(129, 242, 121)
 
    Private innerBackgroundRegion As Region
    Private segmentPaths(11) As Drawing2D.GraphicsPath
 
    Private m_AutoIncrement As Boolean = True
    Private m_IncrementFrequency As Double = 100
    Private m_BehindIsActive As Boolean = True
    Private m_TransitionSegment As Integer = 0
 
    Private m_AutoRotateTimer As System.Timers.Timer
 
    <System.ComponentModel.DefaultValue(GetType(Color), "218, 218, 218")> _
    Property InactiveSegmentColour() As Color
        Get
            Return m_InactiveColour
        End Get
        Set(ByVal value As Color)
            m_InactiveColour = value
            Invalidate()
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(GetType(Color), "35, 146, 33")> _
    Property ActiveSegmentColour() As Color
        Get
            Return m_ActiveColour
        End Get
        Set(ByVal value As Color)
            m_ActiveColour = value
            Invalidate()
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(GetType(Color), "129, 242, 121")> _
    Property TransistionSegmentColour() As Color
        Get
            Return m_TransistionColour
        End Get
        Set(ByVal value As Color)
            m_TransistionColour = value
            Invalidate()
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(True)> _
    Property BehindTransistionSegmentIsActive() As Boolean
        Get
            Return m_BehindIsActive
        End Get
        Set(ByVal value As Boolean)
            m_BehindIsActive = value
            Invalidate()
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(-1)> _
    Property TransistionSegment() As Integer
        Get
            Return m_TransitionSegment
        End Get
        Set(ByVal value As Integer)
            If value > 11 Or value < -1 Then
                Throw New ArgumentException("TransistionSegment must be between -1 and 11")
            End If
            m_TransitionSegment = value
            Invalidate()
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(True)> _
    Property AutoIncrement() As Boolean
        Get
            Return m_AutoIncrement
        End Get
        Set(ByVal value As Boolean)
            m_AutoIncrement = value
 
            If Not m_AutoRotateTimer Is Nothing Then
                'If Not m_AutoRotateTimer Is Nothing And value = False Then
                m_AutoRotateTimer.Dispose()
                m_AutoRotateTimer = Nothing
            End If
 
            If value = True AndAlso m_AutoRotateTimer Is Nothing Then
                m_AutoRotateTimer = New System.Timers.Timer(m_IncrementFrequency)
                AddHandler m_AutoRotateTimer.Elapsed, AddressOf IncrementTransisionSegment
                m_AutoRotateTimer.Start()
            End If
        End Set
    End Property
 
    <System.ComponentModel.DefaultValue(CDbl(100))> _
    Property AutoIncrementFrequency() As Double
        Get
            Return m_IncrementFrequency
        End Get
        Set(ByVal value As Double)
            m_IncrementFrequency = value
 
            If Not m_AutoRotateTimer Is Nothing Then
                AutoIncrement = False
                AutoIncrement = True
            End If
        End Set
    End Property
 
    Private Sub IncrementTransisionSegment(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
        Try
 
  
        If m_TransitionSegment = 11 Then
            m_TransitionSegment = 0
            m_BehindIsActive = Not m_BehindIsActive
        ElseIf m_TransitionSegment = -1 Then
            m_TransitionSegment = 0
        Else
            m_TransitionSegment += 1
        End If
 
            Invalidate()
            Me.Refresh()
 
        Catch ex As Exception
            MsgBox("Spinning Progress error traped; " & ex.Message, MsgBoxStyle.OkOnly)
        End Try
 
    End Sub
 
    Private Sub CalculateSegments()
        Try
            Dim rctFull As New Rectangle(0, _
                                         0, _
                                         Me.Width, _
                                         Me.Height)
            Dim rctInner As New Rectangle(CInt(Me.Width * (7 / 30)), _
                                          CInt(Me.Height * (7 / 30)), _
                                          CInt(Me.Width - (Me.Width * (7 / 30) * 2)), _
                                          CInt(Me.Height - (Me.Height * (7 / 30) * 2)))
            Dim pthInnerBackground As Drawing2D.GraphicsPath
 
            'Create 12 segment pieces
            For intCount As Integer = 0 To 11
                segmentPaths(intCount) = New Drawing2D.GraphicsPath
 
                'We subtract 90 so that the starting segment is at 12 o'clock
                segmentPaths(intCount).AddPie(rctFull, (intCount * 30) - 90, 25)
            Next
 
            'Create the center circle cut-out
            pthInnerBackground = New Drawing2D.GraphicsPath
            pthInnerBackground.AddPie(rctInner, 0, 360)
            innerBackgroundRegion = New Region(pthInnerBackground)
        Catch ex As Exception
            'MsgBox("Spinning Progress error traped", MsgBoxStyle.OKOnly)
        End Try
    End Sub
 
    Private Sub ProgressDisk_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
        CalculateSegments()
    End Sub
 
    Private Sub ProgressDisk_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged
        CalculateSegments()
    End Sub
 
    Private Sub SpinningProgress_EnabledChanged1(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.EnabledChanged
        Try
            If Enabled = True Then
                If Not m_AutoRotateTimer Is Nothing Then
                    m_AutoRotateTimer.Start()
                End If
            Else
                If Not m_AutoRotateTimer Is Nothing Then
                    m_AutoRotateTimer.Stop()
                End If
            End If
        Catch ex As Exception
            'MsgBox("Spinning Progress error traped", MsgBoxStyle.OKOnly)
        End Try
    End Sub
 
    Private Sub SpinningProgress_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Try
            e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            e.Graphics.ExcludeClip(innerBackgroundRegion)
 
            For intCount As Integer = 0 To 11
                If Me.Enabled Then
                    If intCount = m_TransitionSegment Then
                        'If this segment is the transistion segment, colour it differently
                        e.Graphics.FillPath(New SolidBrush(m_TransistionColour), segmentPaths(intCount))
                    ElseIf intCount < m_TransitionSegment Then
                        'This segment is behind the transistion segment
                        If m_BehindIsActive Then
                            'If behind the transistion should be active, 
                            'colour it with the active colour
                            e.Graphics.FillPath(New SolidBrush(m_ActiveColour), segmentPaths(intCount))
                        Else
                            'If behind the transistion should be in-active, 
                            'colour it with the in-active colour
                            e.Graphics.FillPath(New SolidBrush(m_InactiveColour), segmentPaths(intCount))
                        End If
                    Else
                        'This segment is ahead of the transistion segment
                        If m_BehindIsActive Then
                            'If behind the the transistion should be active, 
                            'colour it with the in-active colour
                            e.Graphics.FillPath(New SolidBrush(m_InactiveColour), segmentPaths(intCount))
                        Else
                            'If behind the the transistion should be in-active, 
                            'colour it with the active colour
                            e.Graphics.FillPath(New SolidBrush(m_ActiveColour), segmentPaths(intCount))
                        End If
                    End If
                Else
                    'Draw all segments in in-active colour if not enabled
                    e.Graphics.FillPath(New SolidBrush(m_InactiveColour), segmentPaths(intCount))
                End If
            Next
 
        Catch ex As Exception
            'MsgBox("Spinning Progress error traped", MsgBoxStyle.OKOnly)
        End Try
    End Sub
 
    Private Sub SpinningProgress_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.TopMost = True
    End Sub
End Class
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 9 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 9 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros