ARTICLE

Using ThreadPool to run animated Gifs in VB.NET

Posted by Mike Gold Articles | Visual Basic 2010 June 15, 2003
One of the nice features incorporated into the .NET framework is the ThreadPool class. In this article we will discuss the use of the ThreadPool class in conjunction with the ImageAnimator class to run 3 animated gifs in separate threads.
Download Files:
 
Reader Level:



Figure 1 - Animated Gifs running in a ThreadPool.

One of the nice features incorporated into the .NET framework is the ThreadPool class. If you are not in the mood to manage your threads (determining when they sleep and when they wake up), you can take advantage of this powerful class consisting of some easy to use static functions. In this article we will discuss the use of the ThreadPool class in conjunction with the ImageAnimator class to run 3 animated gifs in separate threads.

The great thing about the ThreadPool class is you don't really have to deal with threads directly. There are two main methods used in this example from the ThreadPool class, each one is described below.

ThreadPool Static  Methods Description
RegisterWaitForSingleObject Used to trigger an Asynchronous callback with an event, if the event doesn't occur in the time out period, it triggers anyway.
QueueUserWorkItem Used to put a new worker thread in the thread pool along with an associated object.

Table 1 - ThreadPool class methods.

ThreadPools have an added advantage over the thread class in that, not only do they allow you to create a thread, but also it lets you pass an object associated with the thread to the thread delegate.  I haven't figured out how to do this with the Thread class yet.  Perhaps in the future, the .NET framework will be more accommodating with this task.

The object you pass into your delegate can be just about anything since it can box the instance of your class. When you call QueueUserWorkItem, you pass in the delegate for your thread as the first parameter, and the associated object as your second parameter.

RegisterWaitForSingleObject has a different purpose. It allows you to trigger a callback function with a WaitHandle or AutoResetEvent. The WaitHandle lets you do things like trigger the callback when all of your threads are complete or any of your threads are complete (it depends upon how you set it up). The AutoResetEvent can be triggered programmatically by setting it to signal that the event occurred.  RegisterWaitForSingleObject also allows you to specify a timeout period, so that if a WaitHandle or AutoResetEvent triggers no event, the callback will be called automatically after the timeout period has expired.

Now we are ready to look at our example code. The RegisterWaitForSingleObject call and QueueUserWorkItems are called initially to set up the threads and callbacks. The first time you call QueueUserWorkItems, the new thread pool is created and also the first thread is created and placed in the thread pool queue.  Below is the sample initialization code for our form full of gif animations.

Public Sub TestAnimations()
' construct AutoResetEvent for signaling "Hi Button".
' Appearance on the form
ev = New AutoResetEvent(False)
button1.Enabled = True
' Set up asynchronous callback trigger using.
' the AutoResetEvent and a 20 second timeout period.
ThreadPool.RegisterWaitForSingleObject(ev, New WaitOrTimerCallback(WaitThreadFunc), "Hi", 20000, False)
' put each thread into the pool for running.
' each animated gif. Pass the name of the gif.
' file into the corresponding thread.
Dim GifFile As String() = {"gif1.gif", "gif2.gif", "gif3.gif"}
Dim i As Integer
For
i = 0 To 2
ThreadPool.QueueUserWorkItem(New WaitCallback(Me.RunAnimation), CType(GifFile(i), Object))
Next i
End Sub 'TestAnimations

Listing 1 - Initializing the thread pool.

The RunAnimation thread Delegate prepares our GIF file for animation using the ImageAnimator class.  The ImageAnimator class has a series of static functions that lets us play our gif file.  Below are the methods used for animating the gif: (Use of  the ImageAnimator can be found in The Complete Visual C# Programmer’s Guide in the GDI+ section at the end of chapter 15). 

ImageAnimator Static Methods Description
Animate Sets up the image and event handler for updating the frame of the animated gif
UpdateFrames Move to the next GIF

Table 2 - ImageAnimator Class Methods.

The RunAnimation thread delegate is shown below. From the code, you can see the initial call to Animate. The image is created from the object passed into the thread which is unboxed to get the name of the image. This string is also used to locate the array position of the image because the file names are conveniently named gif1, gif2, and gif3 in this example:

Sub RunAnimation(filename As Object)
' Image is created from the filename.
Dim theImage As Image = Image.FromFile(CStr(filename))
' the image is set up for animation using the
' ImageAnimator class and an event handler.
ImageAnimator.Animate(theImage, New EventHandler(Me.OnFrameChanged))
' we also need to parse the image name to
' determine the position of the gif in the array
Dim name As String = CStr(filename)
Dim periodPosition As Integer = name.LastIndexOf(".")
periodPosition -= 1 ' get number.
Dim index As Integer = Convert.ToInt32(name(periodPosition).ToString())
Gifs((index - 1)) = theImage
End Sub 'RunAnimation.

Listing 2 - Initial code for starting the Animated Gif file.

OnFrameChanged is called each time the UpdateFrame is called for the image.  Inside OnFrameChanged we call invalidate to force a repaint of the gif and a subsequent call to UpdateFrame:

Private Sub OnFrameChanged(o As Object, e As EventArgs)
Me.Invalidate() ' force a repaint of the gif.
End Sub 'OnFrameChanged.

Listing 3 - Event Handler for UpdateFrame event of the Animated Gif.

All of the paintings of the Gifs are handled in the OnPaint event. Each thread will trigger the OnPaint event through the OnFrameChanged Event, which is also contained in the individual threads. The Paint Event Handler, shown below, does the painting of the images for all three threads:   

Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs)
'Get the next frame ready for rendering for the image in this thread.
ImageAnimator.UpdateFrames()
Dim g As Graphics = e.Graphics
'Draw the current frame in the animation for all of the images.
Dim i As Integer
For
i = 0 To 2
If Not (Gifs(i) Is Nothing) Then
g.DrawImage(Gifs(i),(i Mod 2) * 150, i / 2 * 150, Gifs(i).Width, Gifs(i).Height)
End If
Next
i
' if AutoReset event was triggered, paint the red circle with the HI.
If AllowHi Then
g.FillEllipse(Brushes.Red, 200, 175, 50, 50)
g.DrawString(CircleString, TheFont, Brushes.Black, 215, 190, New StringFormat())
End
If
End
Sub 'Form1_Paint.

Listing 4 - Painting the Gif Images on the Form.

You'll also note in the listing above the AllowHi boolean flag. This flag is set in the callback after WaitForSingleObject callback is triggered (either by setting the signal of the AutoResetEvent or by timing out after 20 seconds). If you click on the Trigger Hi button on the form, it signals the AutoResetEvent  (by calling Set), which in turn triggers the WaitForSingleObject callback.

The callback delegate passed by the WaitForSingleObject method of the ThreadPool is shown below:

Sub WaitThreadFunc(test As Object, b As Boolean)
AllowHi = True
CircleString = CStr(test)
End Sub 'WaitThreadFunc.

Notice that you can also pass an object into the callback from the WaitForSingleObject function of the ThreadPool. In this case a string with the message displayed in the red circle is passed into the method.

The behavior the combined code exhibits when running the example is the following.  

  1. If the button is pressed, the red circle with the "Hi" pops up immediately.
  2. If the button is not pressed, the red circle with the "Hi" will show up anyway after 20 seconds (the timeout period).

Conclusion.

Thread pools are a no-brainer way to implement thread management and the ThreadPool class gives us the tools we need to create and manage threads. The gifs were brought to you courtesy of a cool artist site I found while searching for animated gifs to use to create this article. The next step, you may have guessed,  is to thread the animated gifs in ASP.NET.

share this article :
post comment
 

nice thanx

Posted by Thirumani Feb 18, 2008
Nevron Diagram
Become a Sponsor
PREMIUM SPONSORS
  • ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
    Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Team Foundation Server Hosting
Become a Sponsor