Timer.Tick of a UserControl is Processor Intesive When There are Multiple Objects

raklali 236 Reputation points
2022-01-02T14:30:05.233+00:00

I have a UserControl that has multiple Common Controls like Buttons, Textbox, Lablels, etc and a Timer. Timer.Tick Handle is used to triggers Three-Four User Functions, every second.

When more than Five UserControl Objects are created, the Processor/ Execution of the Program slows down drastically.

What is the better way to trigger events of **Mutliple ** UserControls?

On Binging, I learnt that implementing Threading instead of Timer is a good idea but I ain't sure How to do that?

Assistance is solicited. Thank you

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,714 questions
{count} votes

Accepted answer
  1. Castorix31 84,546 Reputation points
    2022-01-02T19:45:30.83+00:00

    I learnt that implementing Threading instead of Timer is a good idea but I ain't sure How to do that?

    Yes, you can use Threads

    For example, a test with a UserControl containing 2 PictureBoxes, with 2 threads drawing bouncing balls
    (which eats a lot of CPU in GDI+ and must not be done (Direct2D or WPF instead), but it is for the test to consume CPU)

    Test with 9 controls (18 threads); animations are not too slower than with 1 control :

    161757-usercontrol-threads.jpg

    (remove the space at S leep (bug of this editor...))

    Imports System.Threading  
      
    Public Class UserControl1  
        Inherits UserControl  
        Friend WithEvents pictureBox1 As PictureBox  
        Friend WithEvents pictureBox2 As PictureBox  
      
        Private wt1 As Thread = Nothing  
        Private wt2 As Thread = Nothing  
        Private ReadOnly isCanceled As AutoResetEvent = New AutoResetEvent(False)  
      
        Private nX1 As Integer = 0, nX2 As Integer = 0, nY1 As Integer = 0, nY2 As Integer = 0  
        Private nStepX1 As Integer = 1, nStepX2 As Integer = 1, nStepY1 As Integer = 1, nStepY2 As Integer = 1  
        Private nSize1 As Integer = 20, nSize2 As Integer = 40  
        Private brush1 As System.Drawing.Brush = System.Drawing.Brushes.Green  
        Private brush2 As System.Drawing.Brush = System.Drawing.Brushes.Red  
      
        Public Sub New()  
            'InitializeComponent()  
            pictureBox1 = New PictureBox()  
            pictureBox1.Location = New System.Drawing.Point(2, 2)  
            pictureBox1.Size = New System.Drawing.Size(CInt((Me.ClientSize.Width - 2 * 3) / 2), Me.ClientSize.Height - 2 * 2)  
            pictureBox1.BorderStyle = BorderStyle.FixedSingle  
            Controls.Add(pictureBox1)  
      
            pictureBox2 = New PictureBox()  
            pictureBox2.Location = New System.Drawing.Point(pictureBox1.Location.X + pictureBox1.Width + 2, 2)  
            pictureBox2.Size = New System.Drawing.Size(CInt(Me.ClientSize.Width / 2 - 2 * 3), Me.ClientSize.Height - 2 * 2)  
            pictureBox2.BorderStyle = BorderStyle.FixedSingle  
            Controls.Add(pictureBox2)  
      
            Dim bDesignMode As Boolean = (System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Designtime)  
            If (Not bDesignMode) Then  
                wt1 = New Thread(New ThreadStart(AddressOf Me.WorkerThread1))  
                wt1.Start()  
      
                wt2 = New Thread(New ThreadStart(AddressOf Me.WorkerThread2))  
                wt2.Start()  
            End If  
      
            Me.BorderStyle = BorderStyle.FixedSingle  
            Me.DoubleBuffered = True  
        End Sub  
      
        Protected Overrides Sub OnCreateControl()  
            MyBase.OnCreateControl()  
            AddHandler CType(Me.Parent, Form).Closing, AddressOf Me.ParentClosing  
        End Sub  
      
        Protected Overrides Sub OnResize(e As EventArgs)  
            MyBase.OnResize(e)  
            pictureBox1.Size = New System.Drawing.Size(CInt((Me.ClientSize.Width - 2 * 3) / 2), Me.ClientSize.Height - 2 * 2)  
            pictureBox2.Location = New System.Drawing.Point(pictureBox1.Location.X + pictureBox1.Width + 2, 2)  
            pictureBox2.Size = New System.Drawing.Size(CInt((Me.ClientSize.Width - 2 * 3) / 2), Me.ClientSize.Height - 2 * 2)  
        End Sub  
      
        Private Sub ParentClosing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)  
            If wt1 IsNot Nothing Then wt1.Abort()  
            If wt2 IsNot Nothing Then wt2.Abort()  
        End Sub  
      
        Private Sub WorkerThread1()  
            Do While Not isCanceled.WaitOne(0)  
                If IsHandleCreated Then  
                    Invoke(New Action(AddressOf DrawItem1))  
                    Thread.S leep(15)  
                End If  
            Loop  
        End Sub  
      
        Private Sub WorkerThread2()  
            Do While Not isCanceled.WaitOne(0)  
                If IsHandleCreated Then  
                    Invoke(New Action(AddressOf DrawItem2))  
                    Thread.S leep(15)  
                End If  
            Loop  
        End Sub    
      
        Private Sub DrawItem1()  
            nX1 += nStepX1  
            nY1 += nStepY1  
            If nX1 >= pictureBox1.Width - nSize1 Then nStepX1 = -1  
            If nY1 >= pictureBox1.Height - nSize1 Then nStepY1 = -1  
            If nX1 < 0 Then nStepX1 = 1  
            If nY1 < 0 Then nStepY1 = 1  
            Dim bm As Bitmap = New Bitmap(pictureBox1.Width, pictureBox1.Height)  
            Using gr As Graphics = Graphics.FromImage(bm)  
                gr.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality  
                gr.FillEllipse(brush1, Convert.ToInt32(nX1), Convert.ToInt32(nY1), nSize1, nSize1)  
            End Using  
            If (pictureBox1.Image IsNot Nothing) Then  
                pictureBox1.Image.Dispose()  
            End If  
            pictureBox1.Image = bm  
        End Sub  
      
        Private Sub DrawItem2()  
            nX2 += nStepX2  
            nY2 += nStepY2  
            If nX2 >= pictureBox2.Width - nSize2 Then nStepX2 = -1  
            If nY2 >= pictureBox2.Height - nSize2 Then nStepY2 = -1  
            If nX2 < 0 Then nStepX2 = 1  
            If nY2 < 0 Then nStepY2 = 1  
            Dim bm As Bitmap = New Bitmap(pictureBox2.Width, pictureBox2.Height)  
            Using gr As Graphics = Graphics.FromImage(bm)  
                gr.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality  
                gr.FillEllipse(brush2, Convert.ToInt32(nX2), Convert.ToInt32(nY2), nSize2, nSize2)  
            End Using  
            If (pictureBox2.Image IsNot Nothing) Then  
                pictureBox2.Image.Dispose()  
            End If  
            pictureBox2.Image = bm  
        End Sub   
    End Class  
      
      
    

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.