Creating Multithreaded Applications in .NET Compact Framework 2.0

Last Updated: Nov 02, 2025
5 min read
Legacy Archive

In .NET Compact Framework, it's possible to create a thread and the created reference can easily be passed to a function. Any function can be defined as an entry point to a new thread, and once the function is performed or executed, the thread can be made to terminate automatically.

To create a multithreaded application using .NET Compact Framework 2.0, you'll select the Smart Device option and then the Pocket PC option for your IDE project. Let's look at how to build applications where multiple threads work together to process data efficiently.

Creating the Process Class

In our example, we'll create two threads that both use methods of another class called Process1. All methods in the Process1 class will be accessed by both threads and used to update the class's data. We'll create two methods in Process1 that will update two different counters within loops.

Process1.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace MultithreadingExample
{
    /// Process1 class that can be accessed by multiple threads.
    /// This class demonstrates the use of Monitor.
    public class Process1
    {
        private const int Loops = 10;
        private int counter1;
        private int counter2;
        
        /// Constructor of the Process1 class.
        public Process1()
        {
            counter1 = 0;
            counter2 = 0;
        }
        
        /// Access some data that Monitor protects.
        public void Action1()
        {
            for (int i = 0; i < Loops; i++)
            {
                // Monitor.Enter(this);
                int localCounter = counter1;
                Thread.Sleep(0);
                localCounter++;
                Thread.Sleep(0);
                counter1 = localCounter;
                Thread.Sleep(0);
                // Monitor.Exit(this);
            }
        }
        
        /// Access some data that Monitor protects.
        public void Action2()
        {
            for (int i = 0; i < Loops; i++)
            {
                // Monitor.Enter(this);
                int localCounter = counter2;
                localCounter++;
                counter2 = localCounter;
                // Monitor.Exit(this);
            }
        }
        
        /// Return the difference in the two counter variables
        /// that have been accessed by multiple threads.
        public int Counter
        {
            get
            {
                return counter1 - counter2;
            }
        }
    }
}

Managing Multiple Threads

The threads will call either Process1.Action1 or Process1.Action2 and update the data depending on the passed values. Once the loop actions are complete, you can make your application return to any of the counters. You'll provide buttons so that threads can be invoked.

Here's the code for managing two threads that work with the Process1 class:

Form1.cs
private Process1 process1;
private bool Thread1Done;
private bool Thread2Done;

private void btnStart_Click(object sender, EventArgs e)
{
    button2.Enabled = false;
    textBox2.Text = "Monitor sample";
    
    process1 = new Process1();
    Thread1Done = false;
    Thread2Done = false;
    
    Thread myThread1 = new Thread(new ThreadStart(MonitorOfThread1));
    Thread myThread2 = new Thread(new ThreadStart(MonitorOfThread2));
    
    myThread1.Start();
    myThread2.Start();
}

private void MonitorOfThread1()
{
    process1.Action1();
    process1.Action2();
    Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
    Thread1Done = true;
    this.Invoke(new EventHandler(ThreadsManagerDone));
}

private void MonitorOfThread2()
{
    process1.Action1();
    process1.Action2();
    Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
    Thread2Done = true;
    this.Invoke(new EventHandler(ThreadsManagerDone));
}

Handling Thread Completion Events

Events are used to indicate when a thread has completed its work in a managed multithreaded environment. You'll need to check when both threads are done and then display the results to the user.

EventHandler.cs
private void ThreadsManagerDone(object sender, System.EventArgs e)
{
    if (Thread1Done && Thread2Done)
    {
        textBox2.Text = "Processing result: " + 
                        process1.Counter.ToString();
        button2.Enabled = true;
    }
}

Thread Synchronization with Monitor

When multiple threads access shared data, you need synchronization to prevent race conditions. The Monitor class provides this functionality. Here's how to properly protect your shared data:

SynchronizedProcess.cs
public void Action1Synchronized()
{
    for (int i = 0; i < Loops; i++)
    {
        Monitor.Enter(this);
        try
        {
            int localCounter = counter1;
            Thread.Sleep(0);
            localCounter++;
            Thread.Sleep(0);
            counter1 = localCounter;
            Thread.Sleep(0);
        }
        finally
        {
            Monitor.Exit(this);
        }
    }
}

Testing on Pocket PC

If your application is meant for Pocket PC, you'll need to ensure the Visual Studio environment is available and enabled on the selected device. For testing successful execution on a Pocket PC, you should initially test it by connecting to an emulator and evaluate the performance.

Any application that employs multiple threads can run faster, and you can achieve great performance with simplified procedures. However, the involved programming complications and debugging methods can make it complex. With the added complications of threads, people may find it difficult to complete the job within the specified time.

Best Practices for Multithreading

You can refer to the MSDN website and learn how to effectively create, modify, and run multithreaded applications. The site can also help you with code samples for creating test multithreading applications that run on .NET Compact Framework 2.0.

Remember to always clean up your threads properly, use synchronization when accessing shared resources, and test thoroughly on actual devices to ensure your multithreaded application performs as expected.

FAQ

What's the purpose of Monitor in multithreaded applications?

Monitor provides synchronization by protecting data that multiple threads access. It uses Monitor.Enter and Monitor.Exit to create critical sections, ensuring only one thread at a time can access protected data, preventing race conditions and data corruption.

How do I set thread priorities in .NET Compact Framework?

Use Thread.CurrentThread.Priority property with values like ThreadPriority.AboveNormal, ThreadPriority.Normal, or ThreadPriority.BelowNormal. Higher priority threads get more CPU time, but use carefully as it can affect application responsiveness.

What are the benefits and drawbacks of multithreading?

Benefits include faster performance and simplified procedures through parallel execution. Drawbacks include programming complexity, difficult debugging, and potential race conditions. The added complexity can make it challenging to complete projects within specified timeframes.

How do I notify the UI thread when background threads complete?

Use Control.Invoke to marshal calls back to the UI thread. Create an EventHandler and invoke it from your background thread. This ensures UI updates happen on the correct thread, avoiding cross-thread operation exceptions.

Back to Articles