In this article we are going to learn about the Thread Pool in Windows Store apps. We can use the thread pool to accomplish work asynchronously in parallel threads.
The thread pool manages a set of threads and uses a queue to assign work items to threads as they become available. Using the Thread Pool you can perform their tasks to complete multiple work items in parallel.
For more information about Thread Pool please visit:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj248675.aspx
In this article I will show an example that creates a Delay timer using a Thread Pool that fires only once after the delay time specified by the user elapses.
Steps to be followed
Step 1
First of all I create a class that keeps track of my thread pool; it is:
class ThreadPoolSample
{
public static ThreadPoolTimer DelayTimer;
public static int DelayTimerMilliseconds = 0;
public static string DelayTimerInfo = "";
public static Status DelayTimerStatus = Status.Unregistered;
public static int DelayTimerSelectedIndex = 0;
public static ThreadPoolTimer PeriodicTimer;
public static long PeriodicTimerCount = 0;
public static int PeriodicTimerMilliseconds = 0;
public static string PeriodicTimerInfo = "";
public static Status PeriodicTimerStatus = Status.Unregistered;
public static int PeriodicTimerSelectedIndex = 0;
public static IAsyncAction ThreadPoolWorkItem;
public static WorkItemPriority WorkItemPriority = WorkItemPriority.Normal;
public static Status WorkItemStatus;
public static int WorkItemSelectedIndex = 1;
}
Step 2
Include the following namespace in the .cs file:
using Windows.System.Threading;
using Windows.UI.Core;
Step 3
Create a single-shot timer.
Use the CreateTimer method of the ThreadPoolTimer Class to create a timer for the work item. Supply the delay parameter to specify how long the thread pool waits before it can assign the work item to an available thread.
private void CreateDelayTimer(object sender, RoutedEventArgs args)
{
if (int.TryParse(DelayMs.SelectionBoxItem.ToString(), out ThreadPoolSample.DelayTimerMilliseconds))
{
ThreadPoolSample.DelayTimer = ThreadPoolTimer.CreateTimer(
async (timer) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
UpdateUI(Status.Completed);
});
},
TimeSpan.FromMilliseconds(ThreadPoolSample.DelayTimerMilliseconds));
UpdateUI(Status.Started);
}
}
Step 4
Cancel the timer.
If the timer is still counting down, but the work item is no longer needed, call Cancel.
private void CancelDelayTimer(object sender, RoutedEventArgs args)
{
if (ThreadPoolSample.DelayTimer != null)
{
ThreadPoolSample.DelayTimer.Cancel();
UpdateUI(Status.Canceled);
}
}
Step 5
Here is the XAML markup code of the page design:
<Page
x:Class="DealyTimerInThreadPool.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DealyTimerInThreadPool"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="Black" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" Grid.Row="1">
<TextBlock Style="{StaticResource BasicTextStyle}" Margin="0,10,10,0" Text="Delay in ms."></TextBlock>
<ComboBox x:Name="DelayMs" SelectedIndex="0">
<ComboBoxItem>0</ComboBoxItem>
<ComboBoxItem>100</ComboBoxItem>
<ComboBoxItem>500</ComboBoxItem>
<ComboBoxItem>1000</ComboBoxItem>
<ComboBoxItem>5000</ComboBoxItem>
<ComboBoxItem>10000</ComboBoxItem>
</ComboBox>
<Button x:Name="CreateDelayTimerButton" Content="Create" Margin="0,0,10,0" Click="CreateDelayTimer" IsEnabled="True" Grid.Row="2"/>
<Button x:Name="CancelDelayTimerButton" Content="Cancel" Margin="0,0,10,0" Click="CancelDelayTimer" IsEnabled="False" Grid.Row="2"/>
</StackPanel>
</Grid>
<Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
<StackPanel>
<TextBlock x:Name="DelayTimerInfo" Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Text="" />
<TextBlock x:Name="DelayTimerStatus" Style="{StaticResource BasicTextStyle}" TextWrapping="Wrap" Text="" />
</StackPanel>
</Grid>
</Grid>
</Page>
Here is the complete code of the MainPage.xaml.cs file:
using System;
using Windows.Foundation;
using Windows.System.Threading;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Navigation;
namespace DealyTimerInThreadPool
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
DelayMs.SelectedIndex = ThreadPoolSample.DelayTimerSelectedIndex;
UpdateUI(ThreadPoolSample.DelayTimerStatus);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ThreadPoolSample.DelayTimerSelectedIndex = DelayMs.SelectedIndex;
}
private void CreateDelayTimer(object sender, RoutedEventArgs args)
{
if (int.TryParse(DelayMs.SelectionBoxItem.ToString(), out ThreadPoolSample.DelayTimerMilliseconds))
{
ThreadPoolSample.DelayTimer = ThreadPoolTimer.CreateTimer(
async (timer) =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
UpdateUI(Status.Completed);
});
},
TimeSpan.FromMilliseconds(ThreadPoolSample.DelayTimerMilliseconds));
UpdateUI(Status.Started);
}
}
private void CancelDelayTimer(object sender, RoutedEventArgs args)
{
if (ThreadPoolSample.DelayTimer != null)
{
ThreadPoolSample.DelayTimer.Cancel();
UpdateUI(Status.Canceled);
}
}
public void UpdateUI(Status status)
{
ThreadPoolSample.DelayTimerStatus = status;
DelayTimerInfo.Text = string.Format("Timer delay = {0} ms.", ThreadPoolSample.DelayTimerMilliseconds);
DelayTimerStatus.Text = status.ToString("g");
var createButtonEnabled = (status == Status.Started);
CreateDelayTimerButton.IsEnabled = !createButtonEnabled;
CancelDelayTimerButton.IsEnabled = createButtonEnabled;
}
}
class ThreadPoolSample
{
public static ThreadPoolTimer DelayTimer;
public static int DelayTimerMilliseconds = 0;
public static string DelayTimerInfo = "";
public static Status DelayTimerStatus = Status.Unregistered;
public static int DelayTimerSelectedIndex = 0;
public static ThreadPoolTimer PeriodicTimer;
public static long PeriodicTimerCount = 0;
public static int PeriodicTimerMilliseconds = 0;
public static string PeriodicTimerInfo = "";
public static Status PeriodicTimerStatus = Status.Unregistered;
public static int PeriodicTimerSelectedIndex = 0;
public static IAsyncAction ThreadPoolWorkItem;
public static WorkItemPriority WorkItemPriority = WorkItemPriority.Normal;
public static Status WorkItemStatus;
public static int WorkItemSelectedIndex = 1;
}
public enum Status
{
Unregistered = 0,
Started = 1,
Canceled = 2,
Completed = 3
}
}
Output
Run the application to see the output. Select the time for the delay.
You will see the status message when the task is started or completed.