Blue Theme Orange Theme Green Theme Red Theme
 
MindFusion's Components
Home | Forums | Videos | Photos | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
World Class ASP.NET Hosting – Click Here for 3 Months Free/NO Setup Fee!
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » Visual C# » Accessing Windows Forms Controls across Threads

Accessing Windows Forms Controls across Threads

Many articles exist on the web regarding properly handling multiple application threads and accessing data across those threads, but this article will aim to remove much of the ambiguity or inacurate information found in many other articles.

Total page views :  4568
Total downloads :  130
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
CrossThreadUI.zip
 
Become a Sponsor


What is Multi-Threading?

Many programmers and non-programmers alike are mystified by how multi-tasking operating systems are able to perform so many tasks simultaneously. I think it's important to note that, in truth, no processor is capable of doing "two things at once". The way "parallel execution" is achieved is by granting a tiny amount of processing time to each application, allowing each application to process a few lines of code at a time, giving the appearance that they are all running at once.

In programming terms, this is achieved through the method of "multi-threading". In this context, each "thread" is a separate set of instructions to be processed in parallel. It's important to understand the concept of what really goes on inside the processor during multi-threaded or "parallel" processing.

How Does Multi-Threading Work?

For the purposes of an example, lets say we have an application that needs to analyze a photograph and try and find what appear to be people's faces. This would require a very complex set of mathematical algorithms to be run against every pixel or colored point within the image. For a large image, this could take a very long time.

Most code statements that perform some kind of data manipulation are "blocking". That is, they prevent the next line of code from executing until they have finished executing. This is called "Synchronous Execution" because each line of code is executed in sequence.

In a multi-threaded environment, child threads can be spawned by existing threads, enabling the parent thread to continue execution while the child thread performs its work. A statement that creates one of these child threads and immediately returns to execute the next line of code is called "Non-blocking". This is called "Asynchronous Execution" because multiple lines of code appear to execute simultaneously.

Let's put it in a metaphor. Imagine your computer's processor is a highway. When there's only one lane, only one car can travel down the road at a time. If a car drives slowly, then every other car behind it is forced to slow down and wait on it. Now, imagine each thread in your application is an additional lane. Now the cars can travel side-by-side, and some can can even outrun others. Now think about the freeway being built out of lines of code and the cars represent the execution of that code.

There are many things to consider when your application runs multiple threads including data synchronization and stability. You wouldn't want Thread A assigning a value to a variable and then Thread B changes that value before Thread A is able to use it. This is what's known as a "Race Condition" (really, not just because I'm using a car analogy). Classes which contain code to prevent these race conditions are considered "Thread Safe". Many classes within the .NET framework are thread safe, but many are not.

The most commonly misused set of .NET types with multi-threading are the System.Windows.Forms controls. These classes are not thread-safe, yet time and again you will find code with improper handling of these objects across thread boundaries. Going back to our highway analogy, thread boundaries would be the lines which define each lane. If one car jumps over to another lane without taking the proper steps of using a turn signal and making sure the lane is clear and... CRASH!

Types which are not thread-safe are like cars with only a front windshield and no side windshields. They can't possibly see what the other cars are doing around them, so the other cars have to make sure they follow the proper procedures if they intend to change lanes.

Changing Lanes

Now to get more specific with Windows Forms controls... All Windows Forms controls inherit from a base class called "System.Windows.Forms.Control". Pretty obvious there. This "Control" class exposes a public Boolean property called "InvokeRequired". This property lets you know if it's ok to access the control from the current thread if it returns a false value.

Basically, this property tells you if it's necessary to invoke the required action on the thread that originally created the control, which would be the case if a child thread was trying to access a control created on the main thread or vise-versa.

Fear Not

"Invoking" is a term used to describe when one thread requests another thread to execute a piece of code. This is accomplished through the use of "delegates".

Delegates are a type-safe way to pass a reference to a method between objects. Here's a basic delegate definition:

delegate void ChangeMyTextDelegate(Control ctrl, string text);

This defines a reference to a method with a return type of "void" and takes two parameters: Control and String. Take a look at the following method that tries to update the text of a specified control.

public static void ChangeMyText(Control ctrl, string text);
{
    ctrl.Text = text;
}


This is all well and good, assuming that the thread that calls this method is the same thread that created the control. If not, we risk having our cars crash into one another.

To counter this, we use the Control's "InvokeRequired" property and the delegate we defined a moment ago. The resulting code looks like this:

delegate void ChangeMyTextDelegate(Control ctrl, string text);
public static void ChangeMyText(Control ctrl, string text)
{
    if (ctrl.InvokeRequired)
    {
        ChangeMyTextDelegate del = new ChangeMyTextDelegate(ChangeMyText);
        ctrl.Invoke(del, ctrl, text)
    }
    else
    {
        ctrl.Text = text;
    }
}


The first line here declares the definition for our delegate. Like before, we define it as a method that returns void, and takes two arguments. Then comes our actual method. The first thing this method does is check to see if we're on the correct thread to access the Control object 'ctrl' passed as the first argument. If an invoke is required, we create a new instance of our delegate and point it at the "ChangeMyText" method. Then, we ask the control to execute the code for us by passing the delegate and the arguments the delegate requires. You might have noticed by now that the delegate's signature matches the signature of the method it represents. This must always be true for a delegate to reference a method.

After the control executes this method for us (on its own thread), "InvokeRequired" will evaluate to false allowing the 'else' block to execute and set the 'Text' property of the control to the string specified in the 'text' argument.

Which Statements Are "Blocking"?

As a rule, practically every statement you code will be blocking. The exception to this rule is if you call a method that begins with the word "Begin". This is a typical coding standard which identifies non-blocking method calls. It's a good syntactic rule to follow when writing your own multi-threaded code, especially if you're writing a reusable class library, since it will help maintain constancy if you hand your DLL to someone else to use. Besides the "Invoke" method we used above, the Control class also exposes a "BeginInvoke" method which does exactly the same thing, except it's a non-blocking statement.

Where Do We Go From Here?

Check out the attached file "CrossThreadUI.cs", which is a single file from a larger class library I've written. Not only does it contain a method almost identical to the example above (called "SetText" in the .cs file), but it also exposes a number of other static methods which enable you to set just about any property on any type of Control object, and some even use reflection to validate the object and argument types. It's a useful helper class and a great way to experience some multi-threaded Windows Forms Control access in action.


Login to add your contents and source code to this article
 About the author
 
Michael Unfried

Michael Unfried is an avid programmer who has been working in the software development field for almost 10 years.  He was worked on a variety of web and desktop application projects including inventory management, online trade journals, document collaboration, billing systems, and data syncronization services.  Currently he works in the renewable energy field, writing market forcasting models and asset management systems.

Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
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.
Dynamic PDF
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.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
Clickatell's SMS Gateway
Clickatell's Developer Solutions allow you to SMS enable any website or application via a range of API's. Learn More about our API connections.
Free access to .NET Memory Management video
Everything you need to know about Garbage Collection, Temporary Objects, Fragmentation, Finalization and common causes of memory leaks in .NET. Watch the video here.
Microsoft Visual Studio 2010 Professional
Microsoft Visual Studio 2010 Professional will launch on April 12, but you can beat the rush and secure your copy today by pre-ordering at the affordable estimated retail price of $549 (US). Pre-order now.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
Developer-Ready ASP.NET 2.0 Web Hosting with 3 MONTHS FREE
Now supporting .NET 3.0 Framework with Windows Workflow Foundation, Windows Communication Foundation (WCF), Windows Presentation Foundation (WPF), windows CardSpace (WCS)! Providing more flexibility for Developers with Web Services Support and a User/Permission Manger. Also supporting MS SQL 2005/2000 with Real-Time Backups, FREE Automated Attach .MDF Tool, FREE SQL Restore and Shrink SQL DB Tools, and SQL
 
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
CrossThreadUI.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
Become a Sponsor
 Comments

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 2010  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.