[Sample of Mar 5th] WPF Multi-threading demo

 

Homepage image
Sample of the Day RSS Feed

Sample Download
C# version:
https://code.msdn.microsoft.com/CSWPFThreading-797c3aff
VB version: https://code.msdn.microsoft.com/VBWPFThreading-510f8fa6

imageToday’s code sample demonstrates multi-threading in WPF applications.  It illustrates two WPF threading models.  The first one divides a long-running process into many snippets of workitems. Then the dispatcher of WPF will pick up the workitems one by one from the queue by their priority. The background workitem does not affect the UI operation, so it just looks like the background workitem is processed by another thread. But actually, all of them are executed in the same thread. This trick is very useful if you want single threaded GUI application, and also want to keep the GUI responsive when doing expensive operations in the UI thread. The second model is similar to the traditional Windows Forms threading model. The background work item is executed in another thread and it calls the Dispatcher. BeginInvoke method to update the UI.

imageYou can find more code samples that demonstrate the most typical programming scenarios by using Microsoft All-In-One Code Framework Sample Browser or Sample Browser Visual Studio extension. They give you the flexibility to search samples, download samples on demand, manage the downloaded samples in a centralized place, and automatically be notified about sample updates. If it is the first time that you hear about Microsoft All-In-One Code Framework, please watch the introduction video on Microsoft Showcase, or read the introduction on our homepage https://1code.codeplex.com/.

 

Introduction

The sample project illustrates two WPF threading models.

The first one divides a long-running process into many snippets of workitems. Then the dispather of WPF will pick up the workitems one by one from the queue by their priority. The background workitem does not affect the UI operation, so it just looks like the background workitem is processed by another thread. But actually, all of them are executed in the same thread. This trick is very useful if you want single threaded GUI application, and also want to keep the GUI responsive when doing expensive operations in the UI thread.

The second model is similar to the traditional WinForm threading model. The background work item is executed in another thread and it calls the Dispatcher. BeginInvoke method to update the UI.

 

Running the Sample

Press F5 to run this application, you will see following result.

image

Using the Code

Long-Running Calculation in UI Thread (Tab1):

When the start button is firstly clicked, the continueCalculating is false, so the codes call Dispatcher. BeginInvoke to execute a first workitem for the CheckNextNumber.

In the CheckNextNumber function, it judge if the current number is a prime number. If yes, it updates the UI directly. If not, it calls BeginInvoke to execute the CheckNextNumber again for the next odd number.

         public void CheckNextNumber() 
        { 
            // Reset flag. 
            fNotAPrime = false; 
 
            for (long i = 3; i <= Math.Sqrt(num); i++) 
            { 
                if (num % i == 0) 
                { 
                    // Set not-a-prime flag to true. 
                    fNotAPrime = true; 
                    break; 
                } 
            } 
 
            // If a prime number. 
            if (!fNotAPrime) 
            { 
                tbPrime.Text = num.ToString(); 
            } 
 
            num += 2; 
            if (continueCalculating) 
            { 
                btnPrimeNumber.Dispatcher.BeginInvoke( 
                    System.Windows.Threading.DispatcherPriority.SystemIdle, 
                    new NextPrimeDelegate(this.CheckNextNumber)); 
            } 
        } 

In the CheckNextNumber function, because the first parameter passed into BeginInvoke is DispatcherPriority.SystemIdle, all of the CheckNextNumber workitem will not break the UI operation.

When the calculation goes on, we can draw in the UI's InkCanvas, this proves that the UI thread is not affected by the "background" long calculation.

 

Blocked Operation in Worker Thread (Tab2)

When the Retrieve Data from Server button is clicked, the click handle retrieveData function is called.

         private void btnRetrieveData_Click(object sender, RoutedEventArgs e) 
        { 
            this.btnRetrieveData.IsEnabled = false; 
            this.btnRetrieveData.Content = "Contacting Server"; 
 
            NoArgDelegate fetcher = new NoArgDelegate( 
                this.RetrieveDataFromServer); 
            fetcher.BeginInvoke(null, null); 
        } 

Then our codes use delegate.BeginInvoke to start a thread from the thread pool. This thread is used to perform the long operation of retrieving data.

         /// <summary> 
        /// Retrieve data in a worker thread. 
        /// </summary> 
        private void RetrieveDataFromServer() 
        { 
            // Simulate the delay from network access. 
            Thread.Sleep(5000); 
 
            // Generate random data to be displayed. 
            Random rand = new Random(); 
            Int32[] data = { 
                               rand.Next(1000), rand.Next(1000),  
                               rand.Next(1000), rand.Next(1000)  
                           }; 
 
            // Schedule the update function in the UI thread. 
            this.Dispatcher.BeginInvoke( 
                System.Windows.Threading.DispatcherPriority.Normal, 
                new OneArgDelegate(UpdateUserInterface), 
                data); 
        } 

We use Thread.Sleep(5000) to simulate a 5 seconds delay here.

The codes generate 4 random numbers as data and update them to the UI by calling the Dispatcher.BeginInvoke(). Since the retrieving operation is executed in another thread, we can draw in the InkCanvas normally.