Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Cool Check Status Indicator Panel for Windows Forms

0.00/5 (No votes)
4 Apr 2015 1  
Thread safe control displays status with icon according to type of message. Tutorial on sending messages around your application using delegates.

Introduction

If you are using multiple threads in your application, it's not convenient to show status on the user interface, because the current thread may not be the startup thread, which is the thread that must be used for updating any Windows Forms controls. This control has thread safe properties to update progress or status from any thread.

But you also have to figure out how to send the message to the control from some far-away thread where your code is working on some long running process like importing data.

Using the Code

This is a simple control that is a panel type of control containing a picture box and an icon. I found some icons on sites that allow free access to some icons without copyright issues.

The properties, e.g. Caption, BackColor, CheckState, etc. are all thread-safe.

Disclaimer: Although the project code you can download works perfectly, the code below, in the article, was 'air-coded' so I'm not 100% sure it will just work if you just paste it in your project. But I am 100% sure that the concepts are valid. Normally you would customize it for your use anyway, and you can always leave a message if you're having a problem with it, and I'll try to answer as I have time.

Say you are working in some thread and you want the user to see some status. Maybe you'd like to show the status on some control, like the one for this article, CoolCheck.

You can just call a delegate that will marshall your status and text to the sub that updates the CoolCheck control. The code in your sub that updates the control does not need to worry about thread safety when updating the control, because the control uses delegates internally to marshall the call to the startup (UI) thread.

But how do you get such a message to the control (which is on some UI), in the first place? 

You use delegates, which are similar to Events, but the difference is that the delegate can be subscribed to by any class anywhere using the following pattern.

Here's how to set up such a delegate. In your working class, where the non-UI thread is crunching your stuff, declare a delegate, but do not instantiate it. 

VB.NET
Public Class WorkBeingDone
 
  'local variable at the class level, so it can be called from anywhere in this class:
  Private mMessage_delegate As Message_from_WorkerThread

  'here's the actual delegate, which will be instantiated from outside this class,
  '  and then passed back in:
  Public Delegate Sub Message_from_WorkerThread(Status as CoolCheck.CoolCheckStates, _
           Message as String)

Public Sub New.....

Now in the constructor of the WorkBeingDone class, you include a parameter for the above delegate, and assign it to the private variable above:

VB.NET
Public Sub New (Item as blah, Zoom as blee, Message as Message_from_WorkerThread)

  mMessage_delegate = Message 

Then, when you are ready to New up your WorkBeingDone class using the above constructor, you do these steps:

  1. Create a sub that will get the message from the delegate. I called it "MessageFromWorkerThread".
  2. Instantiate a new variable for the delegate that is inside the WorkBeingDone class. Part of that declaration is to specify the sub in step 1, that will get actuated when the delegate is invoked. (using "AddressOf" - see code below)
  3. Pass the variable created in step 2 - into the new WorkBeingDone class you are instantiating.

It's a tricky mental exercise. You get the delegate out of the WorkBeingDone class, then you pass it back in to that class via the constructor!! Why? Because when you "get" the delegate by making a new copy of it, that's when you also "hook it up" to the sub that will be sent the message from the WorkBeingDone class. Twisty, eh? If you don't get it, you're like me when I first started using them. You'll get it !! Try it.

You see in the following both the declaration of the delegate, passing it back into the WorkBeingDone class, and wiring it up to the sub MessageFromWorkerThread.

VB.NET
Public Class MyClass_That_Does_CoolThings

Private Sub StartupTheWorker

  Dim Wallawalla as New blah
  Dim Bumma as New blee

  Dim Message as New WorkBeingDone.Message_from_WorkerThread (AddressOf MessageFromWorkerThread)

  Dim WorkerClass as New WorkBeingDone (Wallawalla, Bumma, Message)
End Sub

Private Sub MessageFromWorkerThread (Status as CoolCheck.CoolCheckStates, Message as String)
   CoolCheckWorkerStatus.A_Status = Status
   CoolCheckWorkerStatus.A_Caption = Message
End Sub

Now the variable mMessage_Delegate is wired from the WorkBeingDone class directly to the class where you got the WorkBeingDone class started. It can be called anywhere from inside the WorkBeingDone class, wherever you are looping through stuff or whatever, by calling it like this:

VB.NET
mMessage_Delegate (CoolCheck.CoolCheckStates.Info, "Yeah, I'm still working. Go have coffee.")

Points of Interest

A control that is thread safe, and how to update it using a delegate from anywhere to anywhere else.

History

  • Version 1

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here