Tag: Threads

  • Simple threading in C#

    Basic threading can quite easily be accomplished in C# by employing just a few lines of code.

    For this situation it is simply a matter of defining the function you wish to be run as a thread, starting that thread and using ‘join’ as a means of waiting for that thread to finish before continuing with the rest of your code.

    The following example show how to launch a function/task as a thread that operates independently of your main control loop:

    using System;
    using System.Threading;
    
    namespace Threads
    {
       class Program
       {
          public static void Main(string[] args)
          {
             // Create and start the thread
             Thread thread = new Thread(new ThreadStart(SomeTaskThatNeedsToFinish));
             thread.Start();
    
             // Does not proceed beyond here until thread function has finished
             thread.Join();
    
             // Once finished your program is free to continue...
             Console.WriteLine("Task completed.  Press a key to exit.");
             Console.ReadKey();
          }
    
          private static void SomeTaskThatNeedsToFinish()
          {
             // Simulate some task that is going to take ~5sec to finish
             Console.WriteLine("Waiting for task to complete...");
             Thread.Sleep(5000);         
          }
       }
    }
    

    When the programs is started the program is still ‘busy’ doing stuff:

    And only continues with the rest of the code when finished:

    Using async and await

    Async is very useful for tasks that will take an indeterminate length of time, or even fail, such as when accessing a web service. Using the async will enable us to perform other tasks while the asynchronous task is still being carried out.

    using System;
    using System.Net.Http;
    using System.Threading.Tasks;
    
    namespace Threads
    {
       class Program
       {
          public static void Main(string[] args)
          {
             var url = AccessTheWebAsync();
             Console.WriteLine("Asynchronous task completed.");
          }
    
          // Any function that implements await has to be an async
          async static Task<int> AccessTheWebAsync()
          {
             // GetStringAsync returns Task<string>. When you await the task you'll get a string (urlContents).
             // (Can you imagine a world without Microsoft?)
             HttpClient client = new HttpClient();
             Task<string> getStringTask = client.GetStringAsync("http://www.microsoft.com");
    
             // If GetStringAsync gets completed quickly all well and good.
             // If GetStringAsync takes a long time it still won't stop us from executing DoOtherWork
             DoOtherWork();
    
             // Resumes when GetStringAsynch complete  
             string urlContents = await getStringTask;  
             return urlContents.Length;
          }
    
          private static void DoOtherWork()
          {
             Console.WriteLine("Performing other tasks while still obtaining website string...");
          }
       }
    }
    
  • Running a WPF Progress bar as a background worker thread

    How to run a WPF progress bar as a background worker thread.

    This code uses ICommand to respond to the user’s request to both and pause start the progress bar background process.

    Step 1: Create a new WPF application

    progressthread1

    Step 2: Create the MainWindow.xaml user interface components

    <Window x:Class="ProgressThread.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ProgressThread"
            mc:Ignorable="d"
            Title="MainWindow" 
            Height="250" Width="525">
    
    
        <Window.DataContext>
            <local:MainWindowViewModel/>
        </Window.DataContext>
    
        <Grid >
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
    
    
            <ProgressBar 
                Value="{Binding CurrentProgress, Mode=OneWay}" 
                Visibility="Visible"
                VerticalAlignment="Center"
                Grid.Row="0"
                Height="60" Width="300"
                Minimum="0" Maximum="100" 
                Name="pbStatus" />
    
            <Button
                Grid.Row="1"
                Width="150" Height="50"
                Command="{Binding Command}"
                Content="{Binding ButtonLabel}"/>
        </Grid>
        
    </Window>
    

    Step 3: Create the ViewModel classes

    BaseViewModel.cs

    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    
    namespace ProgressThread
    {
        public abstract class BaseViewModel : INotifyPropertyChanged
        {
            #region INotifyPropertyChanged Members
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            #endregion
    
            protected void OnPropertyChanged(string propertyName)
            {
                VerifyPropertyName(propertyName);
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            protected void OnPropertyChanged(int propertyValue)
            {
                VerifyPropertyName(propertyValue);
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyValue.ToString()));
                }
            }
    
            [Conditional("DEBUG")]
            private void VerifyPropertyName(string propertyName)
            {
                if (TypeDescriptor.GetProperties(this)[propertyName] == null)
                    throw new ArgumentNullException(GetType().Name + " does not contain property: " + propertyName);
            }
    
            [Conditional("DEBUG")]
            private void VerifyPropertyName(int propertyValue)
            {
                if (TypeDescriptor.GetProperties(this)[propertyValue] == null)
                    throw new ArgumentNullException(GetType().Name + " does not contain property: " + propertyValue.ToString());
            }
        }
    }
    

    MainWindowViewModel.cs

    using System.ComponentModel;
    using System.Threading;
    using System.Windows;
    using System.Windows.Input;
    
    namespace ProgressThread
    {
        public class MainWindowViewModel : BaseViewModel
        {
            private static bool _isRunning;
            private string _buttonLabel;
            private int currentProgress;
            private ICommand _command;
            private BackgroundWorker worker = new BackgroundWorker();
    
            public MainWindowViewModel()
            {
                worker.DoWork += DoWork;
                worker.ProgressChanged += ProgressChanged;
                worker.WorkerReportsProgress = true;
                worker.WorkerSupportsCancellation = true;
                CurrentProgress = 0;
                _isRunning = true;
                ButtonLabel = "GO";
            }
    
            private void ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                CurrentProgress = e.ProgressPercentage;
            }
    
            private void DoWork(object sender, DoWorkEventArgs e)
            {
                if (CurrentProgress >= 100)
                {
                    CurrentProgress = 0;
                }
    
                while (CurrentProgress < 100 && !_isRunning)
                {
                    worker.ReportProgress(CurrentProgress);
                    Thread.Sleep(100);
                    CurrentProgress++;
                }
    
                _isRunning = true;
            }
    
            public ICommand Command
            {
                get
                {
                    return _command ?? (_command = new RelayCommand(x =>
                    {
                        _isRunning = !_isRunning;
    
                        if (!_isRunning)
                        {
                            DoStuff();
                        }
                        else
                        {
                            ButtonLabel = "PAUSED";
                        }
                    }));
                }
            }
    
            public int CurrentProgress
            {
                get { return currentProgress; }
                private set
                {
                    if (currentProgress != value)
                    {
                        currentProgress = value;
                        OnPropertyChanged("CurrentProgress");
                    }
                }
            }
    
            public string ButtonLabel
            {
                get { return _buttonLabel; }
                private set
                {
                    if (_buttonLabel != value)
                    {
                        _buttonLabel = value;
                        OnPropertyChanged("ButtonLabel");
                    }
                }
            }
    
            private void DoStuff()
            {
                ButtonLabel = "GO";
                worker.RunWorkerAsync();
            }
        }
    }
    

    Step 3: Add the event handling infratructure

    EventArgs.cs

    using System;
    
    namespace ProgressThread
    {
        public class EventArgs<T> : EventArgs
        {
            public EventArgs(T value)
            {
                Value = value;
            }
    
            public T Value { get; private set; }
        }
    }
    
    

    EventRaiser.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ProgressThread
    {
        public static class EventRaiser
        {
            public static void Raise(this EventHandler handler, object sender)
            {
                if (handler != null)
                {
                    handler(sender, EventArgs.Empty);
                }
            }
    
            public static void Raise<T>(this EventHandler<EventArgs<T>> handler, object sender, T value)
            {
                if (handler != null)
                {
                    handler(sender, new EventArgs<T>(value));
                }
            }
    
            public static void Raise<T>(this EventHandler<T> handler, object sender, T value) where T : EventArgs
            {
                if (handler != null)
                {
                    handler(sender, value);
                }
            }
    
            public static void Raise<T>(this EventHandler<EventArgs<T>> handler, object sender, EventArgs<T> value)
            {
                if (handler != null)
                {
                    handler(sender, value);
                }
            }
        }
    }
    
    

    RelayCommand.cs

    using System;
    using System.Windows.Input;
    
    namespace ProgressThread
    {
        public class RelayCommand<T> : ICommand
        {
            private readonly Predicate<T> _canExecute;
            private readonly Action<T> _execute;
    
            public RelayCommand(Action<T> execute)
                : this(execute, null)
            {
                _execute = execute;
            }
    
            public RelayCommand(Action<T> execute, Predicate<T> canExecute)
            {
                if (execute == null)
                {
                    throw new ArgumentNullException("execute");
                }
                _execute = execute;
                _canExecute = canExecute;
            }
    
            public bool CanExecute(object parameter)
            {
                return _canExecute == null || _canExecute((T)parameter);
            }
    
            public void Execute(object parameter)
            {
                _execute((T)parameter);
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
        }
    
        public class RelayCommand : ICommand
        {
            private readonly Predicate<object> _canExecute;
            private readonly Action<object> _execute;
    
            public RelayCommand(Action<object> execute)
                : this(execute, null)
            {
                _execute = execute;
            }
    
            public RelayCommand(Action<object> execute, Predicate<object> canExecute)
            {
                if (execute == null)
                {
                    throw new ArgumentNullException("execute");
                }
                _execute = execute;
                _canExecute = canExecute;
            }
    
            public bool CanExecute(object parameter)
            {
                return _canExecute == null || _canExecute(parameter);
            }
    
            public void Execute(object parameter)
            {
                _execute(parameter);
            }
    
            // Ensures WPF commanding infrastructure asks all RelayCommand objects whether their
            // associated views should be enabled whenever a command is invoked 
            public event EventHandler CanExecuteChanged
            {
                add
                {
                    CommandManager.RequerySuggested += value;
                    CanExecuteChangedInternal += value;
                }
                remove
                {
                    CommandManager.RequerySuggested -= value;
                    CanExecuteChangedInternal -= value;
                }
            }
    
            private event EventHandler CanExecuteChangedInternal;
    
            public void RaiseCanExecuteChanged()
            {
                CanExecuteChangedInternal.Raise(this);
            }
        }
    }
    

    So that when running we initially have the zero-progress as shown:

    progressthread2

    Clicking on the “GO” button initiates the progress bar thread as shown:

    progressthread3

    We can interrupt the progress by clicking on the “GO” button, which stops the background thread and switches the button label to “PAUSED”:

    progressthread4


  • Java Threads: The Basics

    Method 1: Write a class that implements the Runnable interface

    (i) Put the thread code in the run() method.

    (ii) Create a thread object by passing a Runnable object as an argument to the Thread constructor. The Thread object now has a Runnable object that implements the run() method. Like this: (new Thread(new MyThread())).start();

    Simple code sample as follows:

    package javathread1;
    
    class MyThread implements Runnable
    {
        public void run()
        {
            //Display info about thread
    	System.out.println(Thread.currentThread());
        }
    }
    
    public class JavaThread1 
    {    
        public static void main(String[] args) 
        {
            // Create the thread
            Thread thread1 = new Thread(new MyThread(), "thread 1");
            
            // Start the thread
            thread1.start();        
        }
    }
    

    Method 2: Declare the class to be a Subclass of the Thread class

    (i) Override the run() method from the Thread class to define the code executed by the thread.

    (ii) Invoke the start() method inherited from the Thread class to make the thread eligible for running.

    Code sample as follows:

    package javathread1;
    
    class MyThread extends Thread 
    {
        public void run() 
        {
    	//Display info about this particular thread
    	System.out.println(Thread.currentThread().getName());
        }
    }
    
    public class JavaThread1 
    {    
        public static void main(String[] args) 
        {      
            Thread thread1 = new MyThread();
            thread1.start();
        }
    }
    
  • Getting Started with Boost Threads in Visual Studio

    Introduction

    This post aims to be an accessible introduction to getting set up with the Boost threads in Visual Studio environments for the first time.  Like with many technical subjects, there is a great deal of information out on the internet, that tells you a lot without actually showing you anything! (more…)

  • Simple Multithreading in C++ / MFC

    Right now I am just starting with a very simple example – no fancy stuff – just a single thread to demonstrate a sequence that updates a counter 20 times per second. (more…)