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 :
(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