Added support for Silverlight and Mono (And more)
Also added: * Join, Choice, and Pipe to SmartThreadPool. * Local performance counters (for Mono, Silverlight, and WindowsCE)
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 334 KiB |
@@ -42,8 +42,8 @@ namespace STPCEDemo
|
||||
}
|
||||
try
|
||||
{
|
||||
int inUse = _stp.InUseThreads;
|
||||
int inPool = _stp.ActiveThreads;
|
||||
int inUse = (int)_stp.PerformanceCountersReader.InUseThreads;
|
||||
int inPool = (int)_stp.PerformanceCountersReader.ActiveThreads;
|
||||
|
||||
usageHistoryControl1.AddValues(inUse, inPool);
|
||||
usageControl1.Value1 = inUse;
|
||||
@@ -62,7 +62,7 @@ namespace STPCEDemo
|
||||
{
|
||||
int count = Convert.ToInt32(spnWorkItemsPerSecond.Value);
|
||||
int sleepDuration = Convert.ToInt32(spnWorkItemDuration.Value);
|
||||
Debug.WriteLine(string.Format("{0}: C = {1}, S = {2}", DateTime.Now.ToString("HH:mm:ss"), count, sleepDuration));
|
||||
//Debug.WriteLine(string.Format("{0}: C = {1}, S = {2}", DateTime.Now.ToString("HH:mm:ss"), count, sleepDuration));
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
_stp.QueueWorkItem(DoWork, sleepDuration);
|
||||
@@ -78,7 +78,7 @@ namespace STPCEDemo
|
||||
Thread.Sleep(sleepDuration);
|
||||
TimeSpan duration = DateTime.Now - start;
|
||||
|
||||
Debug.WriteLine(string.Format("{0}: Duration = {1}", DateTime.Now.ToString("HH:mm:ss"), duration.TotalMilliseconds));
|
||||
//Debug.WriteLine(string.Format("{0}: Duration = {1}", DateTime.Now.ToString("HH:mm:ss"), duration.TotalMilliseconds));
|
||||
|
||||
//return null;
|
||||
}
|
||||
@@ -93,10 +93,14 @@ namespace STPCEDemo
|
||||
btnStartStop.Text = newRunningState ? "Stop" : "Start";
|
||||
if (newRunningState)
|
||||
{
|
||||
_stp = new SmartThreadPool(
|
||||
Convert.ToInt32(spnIdleTimeout.Value) * 1000,
|
||||
Convert.ToInt32(spnMaxThreads.Value),
|
||||
Convert.ToInt32(spnMinThreads.Value));
|
||||
STPStartInfo stpStartInfo = new STPStartInfo()
|
||||
{
|
||||
IdleTimeout = Convert.ToInt32(spnIdleTimeout.Value) * 1000,
|
||||
MaxWorkerThreads = Convert.ToInt32(spnMaxThreads.Value),
|
||||
MinWorkerThreads = Convert.ToInt32(spnMinThreads.Value),
|
||||
EnableLocalPerformanceCounters = true,
|
||||
};
|
||||
_stp = new SmartThreadPool(stpStartInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -105,6 +109,9 @@ namespace STPCEDemo
|
||||
_stp.Shutdown();
|
||||
}
|
||||
_stp = null;
|
||||
usageHistoryControl1.Reset();
|
||||
usageControl1.Value1 = 0;
|
||||
usageControl1.Value2 = 0;
|
||||
}
|
||||
spnIdleTimeout.Enabled = !newRunningState;
|
||||
uiTimer.Enabled = newRunningState;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -72,16 +72,6 @@
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>
|
||||
</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="STPSLDemo.App"
|
||||
>
|
||||
<Application.Resources>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
|
||||
public App()
|
||||
{
|
||||
this.Startup += this.Application_Startup;
|
||||
this.Exit += this.Application_Exit;
|
||||
this.UnhandledException += this.Application_UnhandledException;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
this.RootVisual = new Page();
|
||||
}
|
||||
|
||||
private void Application_Exit(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
|
||||
{
|
||||
// If the app is running outside of the debugger then report the exception using
|
||||
// the browser's exception mechanism. On IE this will display it a yellow alert
|
||||
// icon in the status bar and Firefox will display a script error.
|
||||
if (!System.Diagnostics.Debugger.IsAttached)
|
||||
{
|
||||
|
||||
// NOTE: This will allow the application to continue running after an exception has been thrown
|
||||
// but not handled.
|
||||
// For production applications this error handling should be replaced with something that will
|
||||
// report the error to the website and stop the application.
|
||||
e.Handled = true;
|
||||
Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
|
||||
}
|
||||
}
|
||||
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
|
||||
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
|
||||
|
||||
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg + "\");");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public class Groupbox : ContentControl
|
||||
{
|
||||
public Groupbox()
|
||||
{
|
||||
DefaultStyleKey = this.GetType();
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderProperty =
|
||||
DependencyProperty.Register("Header", typeof(object), typeof(Groupbox), null);
|
||||
|
||||
public object Header
|
||||
{
|
||||
get { return GetValue(HeaderProperty); }
|
||||
set { SetValue(HeaderProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderTemplateProperty =
|
||||
DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(Groupbox), null);
|
||||
|
||||
|
||||
public DataTemplate HeaderTemplate
|
||||
{
|
||||
get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
|
||||
set { SetValue(HeaderTemplateProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:STPSLDemo="clr-namespace:STPSLDemo"
|
||||
>
|
||||
<Style TargetType="STPSLDemo:Groupbox" >
|
||||
<Setter Property="BorderBrush" Value="DarkGray"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="STPSLDemo:Groupbox">
|
||||
<Grid Background="{TemplateBinding Background}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="1" Grid.RowSpan="2" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3" />
|
||||
<ContentPresenter Grid.Row="2" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
|
||||
<ContentControl Margin="6,0,0,0" Grid.Row="0" Grid.RowSpan="2">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter Margin="2,0,2,0" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"/>
|
||||
</Border>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,147 @@
|
||||
<UserControl x:Class="STPSLDemo.Page"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:STPSLDemo="clr-namespace:STPSLDemo"
|
||||
Width="Auto" Height="Auto" Loaded="UserControl_Loaded">
|
||||
<UserControl.Resources>
|
||||
<Style x:Name="GroupboxStyle" TargetType="STPSLDemo:Groupbox">
|
||||
<Setter Property="BorderBrush" Value="DarkGray"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="STPSLDemo:Groupbox">
|
||||
<Grid Background="{TemplateBinding Background}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Border BorderThickness="{TemplateBinding BorderThickness}" Grid.Row="1" Grid.RowSpan="2" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3" />
|
||||
<ContentPresenter Grid.Row="2" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/>
|
||||
<ContentControl Margin="6,0,0,0" Grid.Row="0" Grid.RowSpan="2">
|
||||
<Border Background="{TemplateBinding Background}">
|
||||
<ContentPresenter Margin="2,0,2,0" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"/>
|
||||
</Border>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid x:Name="LayoutRoot" Background="White" Margin="10,10,10,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="20"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="Test Smart Thread Pool" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Grid.ColumnSpan="5"/>
|
||||
|
||||
<!--<TextBlock Text="STP Usage" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"/>-->
|
||||
<!--<TextBlock Text="STP History Usage" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="3"/>-->
|
||||
|
||||
<STPSLDemo:Groupbox Header="STP Usage" Style="{StaticResource GroupboxStyle}" Grid.Row="2" Grid.Column="1" >
|
||||
<STPSLDemo:UsageControl x:Name="_usageControl" Value1="90" Value2="100" Width="36"/>
|
||||
</STPSLDemo:Groupbox>
|
||||
|
||||
<STPSLDemo:Groupbox Header="STP History Usage" Style="{StaticResource GroupboxStyle}" Grid.Row="2" Grid.Column="3" >
|
||||
<STPSLDemo:UsageHistoryControl x:Name="_historyUsageControl" Height="100" Width="400"/>
|
||||
</STPSLDemo:Groupbox>
|
||||
|
||||
<StackPanel Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="3" Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:Groupbox Header="Work Items" Style="{StaticResource GroupboxStyle}">
|
||||
<Grid >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="50"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="Queued" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" />
|
||||
<TextBlock Text="Generated" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="1" Grid.Column="0"/>
|
||||
<TextBlock Text="Completed" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="2" Grid.Column="0"/>
|
||||
|
||||
<TextBlock x:Name="_queuedWorkItems" Text="0" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" />
|
||||
<TextBlock x:Name="_generatedWorkItems" Text="0" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
|
||||
<TextBlock x:Name="_completedWorkItems" Text="0" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="2" Grid.Column="1"/>
|
||||
|
||||
|
||||
</Grid>
|
||||
</STPSLDemo:Groupbox>
|
||||
<TextBlock Width="20"/>
|
||||
<STPSLDemo:Groupbox Header="Threads" Style="{StaticResource GroupboxStyle}">
|
||||
<Grid >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="50"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="In pool (Red)" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0" />
|
||||
<TextBlock Text="Used (Green)" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="1" Grid.Column="0"/>
|
||||
|
||||
<TextBlock x:Name="_threadsInPool" Text="0" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" />
|
||||
<TextBlock x:Name="_threadsUsed" Text="0" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</STPSLDemo:Groupbox>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="5" Orientation="Vertical" HorizontalAlignment="Left" Margin="0,10,0,0">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:SpinButton x:Name="_spinMinThreads" ValueChanged="_spinMinThreads_ValueChanged" Maximum="25"/>
|
||||
<TextBlock Text="Minimum Threads" VerticalAlignment="Center" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:SpinButton x:Name="_spinMaxThreads" ValueChanged="_spinMaxThreads_ValueChanged" Minimum="1" Maximum="25"/>
|
||||
<TextBlock Text="Maximum Threads" VerticalAlignment="Center" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:SpinButton x:Name="_spinIdleTimeout" Minimum="1" Maximum="100"/>
|
||||
<TextBlock Text="Idle Timeout (Seconds)" VerticalAlignment="Center" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:SpinButton x:Name="_spinInterval" ValueChanged="_spinInterval_ValueChanged" Minimum="0" Maximum="100000" Step="100"/>
|
||||
<TextBlock Text="Interval between work item production (milliseconds)" VerticalAlignment="Center" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<STPSLDemo:SpinButton x:Name="_spinWorkItemTime" ValueChanged="_spinWorkItemTime_ValueChanged" Minimum="0" Maximum="100000" Step="100"/>
|
||||
<TextBlock Text="Work item consuming time (milliseconds)" VerticalAlignment="Center" Margin="20,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="6" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20,0,0">
|
||||
<Button x:Name="btnStart" Content="Start" Width="50" Click="Start_Click"/>
|
||||
<TextBlock Width="20"/>
|
||||
<Button x:Name="btnStop" Content="Stop" Width="50" Click="Stop_Click" IsEnabled="False"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using Amib.Threading;
|
||||
using System.Threading;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public partial class Page : UserControl
|
||||
{
|
||||
private System.Windows.Threading.DispatcherTimer _timer;
|
||||
|
||||
private SmartThreadPool _stp;
|
||||
private bool running;
|
||||
|
||||
private int workItemsCompleted;
|
||||
private int workItemsGenerated;
|
||||
private Thread workItemsProducerThread;
|
||||
|
||||
private int _interval = 0;
|
||||
private int _consumingTime = 0;
|
||||
|
||||
public Page()
|
||||
{
|
||||
InitializeComponent();
|
||||
_timer = new DispatcherTimer();
|
||||
_timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
|
||||
_timer.Tick += _timer_Tick;
|
||||
_timer.Start();
|
||||
|
||||
_spinMinThreads.Value = 0;
|
||||
_spinMaxThreads.Value = 10;
|
||||
_spinIdleTimeout.Value = 5;
|
||||
_spinWorkItemTime.Value = 100;
|
||||
_spinInterval.Value = 100;
|
||||
}
|
||||
|
||||
void _timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
SmartThreadPool stp = _stp;
|
||||
if (null == stp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int threadsInUse = (int)_stp.PerformanceCountersReader.InUseThreads;
|
||||
int threadsInPool = (int)_stp.PerformanceCountersReader.ActiveThreads;
|
||||
|
||||
_threadsUsed.Text = threadsInUse.ToString();
|
||||
_threadsInPool.Text = threadsInPool.ToString();
|
||||
_queuedWorkItems.Text = _stp.PerformanceCountersReader.WorkItemsQueued.ToString();
|
||||
_usageControl.Value1 = threadsInUse;
|
||||
_usageControl.Value2 = threadsInPool;
|
||||
_completedWorkItems.Text = _stp.PerformanceCountersReader.WorkItemsProcessed.ToString();
|
||||
_generatedWorkItems.Text = workItemsGenerated.ToString();
|
||||
_historyUsageControl.AddValues(threadsInUse, threadsInPool);
|
||||
}
|
||||
|
||||
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
UpdateControls(false);
|
||||
}
|
||||
|
||||
private void Start_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
btnStart.IsEnabled = false;
|
||||
btnStop.IsEnabled = true;
|
||||
|
||||
UpdateControls(true);
|
||||
workItemsCompleted = 0;
|
||||
workItemsGenerated = 0;
|
||||
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.IdleTimeout = _spinIdleTimeout.Value * 1000;
|
||||
stpStartInfo.MaxWorkerThreads = _spinMaxThreads.Value;
|
||||
stpStartInfo.MinWorkerThreads = _spinMinThreads.Value;
|
||||
stpStartInfo.EnableLocalPerformanceCounters = true;
|
||||
|
||||
_stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
workItemsProducerThread = new Thread(WorkItemsProducer) {IsBackground = true};
|
||||
workItemsProducerThread.Start();
|
||||
}
|
||||
|
||||
private void Stop_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
running = false;
|
||||
workItemsProducerThread.Join();
|
||||
|
||||
_stp.Shutdown(true, 1000);
|
||||
_stp.Dispose();
|
||||
_stp = null;
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
UpdateControls(false);
|
||||
}
|
||||
|
||||
private void UpdateControls(bool start)
|
||||
{
|
||||
running = start;
|
||||
_spinIdleTimeout.IsEnabled = !start;
|
||||
btnStart.IsEnabled = !start;
|
||||
|
||||
btnStop.IsEnabled = start;
|
||||
if (start)
|
||||
{
|
||||
_timer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
_threadsUsed.Text = "0";
|
||||
_threadsInPool.Text = "0";
|
||||
_queuedWorkItems.Text = "0";
|
||||
_usageControl.Maximum = _spinMaxThreads.Maximum;
|
||||
_usageControl.Value1 = 0;
|
||||
_usageControl.Value2 = 0;
|
||||
_completedWorkItems.Text = "0";
|
||||
_generatedWorkItems.Text = "0";
|
||||
_historyUsageControl.Reset();
|
||||
_historyUsageControl.Maximum = _spinMaxThreads.Maximum;
|
||||
}
|
||||
|
||||
|
||||
private void WorkItemsProducer()
|
||||
{
|
||||
WorkItemCallback workItemCallback = DoWork;
|
||||
while (running)
|
||||
{
|
||||
IWorkItemsGroup workItemsGroup = _stp;
|
||||
if (null == workItemsGroup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
workItemsGroup.QueueWorkItem(workItemCallback);
|
||||
}
|
||||
catch (ObjectDisposedException e)
|
||||
{
|
||||
e.GetHashCode();
|
||||
break;
|
||||
}
|
||||
workItemsGenerated++;
|
||||
Thread.Sleep(_interval);
|
||||
}
|
||||
}
|
||||
|
||||
private object DoWork(object obj)
|
||||
{
|
||||
Thread.Sleep(_consumingTime);
|
||||
Interlocked.Increment(ref workItemsCompleted);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void _spinMinThreads_ValueChanged(int newValue)
|
||||
{
|
||||
if (newValue > _spinMaxThreads.Value)
|
||||
{
|
||||
_spinMaxThreads.Value = newValue;
|
||||
if (null != _stp)
|
||||
{
|
||||
_stp.MaxThreads = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (null != _stp)
|
||||
{
|
||||
_stp.MinThreads = newValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void _spinMaxThreads_ValueChanged(int newValue)
|
||||
{
|
||||
if (newValue < _spinMinThreads.Value)
|
||||
{
|
||||
_spinMinThreads.Value = newValue;
|
||||
_usageControl.Maximum = newValue;
|
||||
_historyUsageControl.Maximum = newValue;
|
||||
if (null != _stp)
|
||||
{
|
||||
_stp.MinThreads = newValue;
|
||||
}
|
||||
}
|
||||
if (null != _stp)
|
||||
{
|
||||
_stp.MaxThreads = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void _spinInterval_ValueChanged(int obj)
|
||||
{
|
||||
_interval = _spinInterval.Value;
|
||||
}
|
||||
|
||||
private void _spinWorkItemTime_ValueChanged(int obj)
|
||||
{
|
||||
_consumingTime = _spinWorkItemTime.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
>
|
||||
<Deployment.Parts>
|
||||
</Deployment.Parts>
|
||||
</Deployment>
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("STPSLDemo")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("STPSLDemo")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("44ee4f12-169f-4949-91f7-efc7100c8be5")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 701 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 735 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 710 B |
@@ -0,0 +1,140 @@
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{44EE4F12-169F-4949-91F7-EFC7100C8BE5}</ProjectGuid>
|
||||
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>STPSLDemo</RootNamespace>
|
||||
<AssemblyName>STPSLDemo</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<SilverlightApplication>true</SilverlightApplication>
|
||||
<SupportedCultures>
|
||||
</SupportedCultures>
|
||||
<XapOutputs>true</XapOutputs>
|
||||
<GenerateSilverlightManifest>true</GenerateSilverlightManifest>
|
||||
<XapFilename>STPSLDemo.xap</XapFilename>
|
||||
<SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
|
||||
<SilverlightAppEntry>STPSLDemo.App</SilverlightAppEntry>
|
||||
<TestPageFileName>TestPage.html</TestPageFileName>
|
||||
<CreateTestPage>true</CreateTestPage>
|
||||
<ValidateXaml>true</ValidateXaml>
|
||||
<ThrowErrorsInValidation>false</ThrowErrorsInValidation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>Bin\Debug</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;SILVERLIGHT=1</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>Bin\Release</OutputPath>
|
||||
<DefineConstants>TRACE;SILVERLIGHT</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows" />
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="system" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Windows.Browser" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Page.xaml.cs">
|
||||
<DependentUpon>Page.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SpinButton.xaml.cs">
|
||||
<DependentUpon>SpinButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UsageControl.xaml.cs">
|
||||
<DependentUpon>UsageControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UsageHistoryControl.xaml.cs">
|
||||
<DependentUpon>UsageHistoryControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Groupbox.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Groupbox.xaml">
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Page.xaml">
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="SpinButton.xaml">
|
||||
<SubType>Page</SubType>
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
</Page>
|
||||
<Page Include="UsageControl.xaml">
|
||||
<SubType>Page</SubType>
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
</Page>
|
||||
<Page Include="UsageHistoryControl.xaml">
|
||||
<SubType>Page</SubType>
|
||||
<Generator>MSBuild:MarkupCompilePass1</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Properties\AppManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SmartThreadPool\SmartThreadPoolSL.csproj">
|
||||
<Project>{A6590A96-22B3-4889-B80E-2C398810E441}</Project>
|
||||
<Name>SmartThreadPoolSL</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\RedCell.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\GreenCell.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\EmptyCell.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
|
||||
<SilverlightProjectProperties />
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -0,0 +1,24 @@
|
||||
<UserControl x:Class="STPSLDemo.SpinButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Width="Auto" Height="Auto" Loaded="UserControl_Loaded">
|
||||
|
||||
<StackPanel Orientation="Horizontal" Width="Auto" Grid.ColumnSpan="4">
|
||||
<!-- Displays the current value. -->
|
||||
<TextBox Name="lblCurrentValue" Background="White"
|
||||
Height="30" Width = "50" VerticalContentAlignment="Center"
|
||||
HorizontalContentAlignment="Center" FontSize="14" />
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<!-- The ‘Up’ button. -->
|
||||
<RepeatButton Height = "15" Width = "15" Name = "repeatAddValueButton" Delay = "200" Interval = "1"
|
||||
Content = "+" FontSize="6" Click="Increment_Click" />
|
||||
|
||||
<!-- The ‘Down’ button. -->
|
||||
<RepeatButton Height = "15" Width = "15"
|
||||
Name = "repeatRemoveValueButton" Delay = "200" Interval = "1"
|
||||
Content = "-" FontSize="6" Click="Decrement_Click" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public partial class SpinButton : UserControl
|
||||
{
|
||||
public SpinButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Step = 1;
|
||||
Value = 5;
|
||||
Maximum = 10;
|
||||
Minimum = 0;
|
||||
}
|
||||
|
||||
private void Increment_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
int newValue = Math.Min(Value + Step, Maximum);
|
||||
if (Value != newValue)
|
||||
{
|
||||
Value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void Decrement_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
int newValue = Math.Max(Value - Step, Minimum);
|
||||
if (Value != newValue)
|
||||
{
|
||||
Value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLabel()
|
||||
{
|
||||
lblCurrentValue.Text = Value.ToString();
|
||||
ValueChanged(Value);
|
||||
}
|
||||
|
||||
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
public event Action<int> ValueChanged = newValue => { };
|
||||
|
||||
|
||||
public static readonly DependencyProperty ValueProperty =
|
||||
DependencyProperty.Register("Value", typeof(int), typeof(SpinButton), null);
|
||||
|
||||
public static readonly DependencyProperty MinimumProperty =
|
||||
DependencyProperty.Register("Minimum", typeof(int), typeof(SpinButton), null);
|
||||
|
||||
public static readonly DependencyProperty MaximumProperty =
|
||||
DependencyProperty.Register("Maximum", typeof(int), typeof(SpinButton), null);
|
||||
|
||||
public static readonly DependencyProperty StepProperty =
|
||||
DependencyProperty.Register("Step", typeof(int), typeof(SpinButton), null);
|
||||
|
||||
public int Value
|
||||
{
|
||||
get { return (int)GetValue(ValueProperty); ; }
|
||||
set
|
||||
{
|
||||
SetValue(ValueProperty, value);
|
||||
UpdateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
public int Step
|
||||
{
|
||||
get { return (int)GetValue(StepProperty); ; }
|
||||
set
|
||||
{
|
||||
SetValue(StepProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Minimum
|
||||
{
|
||||
get { return (int)GetValue(MinimumProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(MinimumProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get { return (int)GetValue(MaximumProperty); }
|
||||
set
|
||||
{
|
||||
SetValue(MaximumProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<UserControl x:Class="STPSLDemo.UsageControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="Auto" Width="Auto">
|
||||
<Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded" Background="Black" Height="100">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="18"/>
|
||||
<ColumnDefinition Width="18"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="4"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0" Grid.Column="0" Width="Auto" Height="Auto">
|
||||
<Border.Background>
|
||||
<ImageBrush ImageSource="Resources/RedCell.jpg"/>
|
||||
</Border.Background>
|
||||
</Border>
|
||||
|
||||
|
||||
<Grid.Resources>
|
||||
<ImageBrush x:Name="EmptyCell" ImageSource="Resources/EmptyCell.jpg"/>
|
||||
<ImageBrush x:Name="GreenCell" ImageSource="Resources/GreenCell.jpg"/>
|
||||
<ImageBrush x:Name="RedCell" ImageSource="Resources/RedCell.jpg"/>
|
||||
</Grid.Resources>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public partial class UsageControl : UserControl
|
||||
{
|
||||
private int _rows = 25;
|
||||
private int _columns = 2;
|
||||
|
||||
private int _max = 100; // Maximum value for progress range
|
||||
private int _value1 = 30; // Current progress
|
||||
private int _value2 = 60; // Current progress
|
||||
|
||||
|
||||
public int Value1
|
||||
{
|
||||
get { return _value1; }
|
||||
set
|
||||
{
|
||||
_value1 = value;
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public int Value2
|
||||
{
|
||||
get { return _value2; }
|
||||
set
|
||||
{
|
||||
_value2 = value;
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get { return _max; }
|
||||
set
|
||||
{
|
||||
_max = value;
|
||||
UpdateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public UsageControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
LayoutRoot.Height = _rows * 4;
|
||||
LayoutRoot.Width = _columns * 18;
|
||||
|
||||
LayoutRoot.RowDefinitions.Clear();
|
||||
|
||||
for (int i = 0; i < _rows; i++)
|
||||
{
|
||||
LayoutRoot.RowDefinitions.Add(new RowDefinition());
|
||||
}
|
||||
|
||||
UpdateDisplay();
|
||||
}
|
||||
|
||||
private void UpdateDisplay()
|
||||
{
|
||||
LayoutRoot.Children.Clear();
|
||||
|
||||
for (int j = 0; j < _columns; j++)
|
||||
{
|
||||
for (int i = 0; i < _rows; i++)
|
||||
{
|
||||
Brush brush = EmptyCell;
|
||||
|
||||
int percent = i * _max / _rows;
|
||||
|
||||
if (percent <= _value2)
|
||||
{
|
||||
brush = RedCell;
|
||||
}
|
||||
|
||||
if (percent <= _value1)
|
||||
{
|
||||
brush = GreenCell;
|
||||
}
|
||||
|
||||
Border border = new Border { Background = brush };
|
||||
|
||||
Grid.SetRow(border, _rows - i - 1);
|
||||
Grid.SetColumn(border, j);
|
||||
LayoutRoot.Children.Add(border);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<UserControl x:Class="STPSLDemo.UsageHistoryControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Width="400" Height="300">
|
||||
<Grid x:Name="LayoutRoot" Background="Black" Loaded="LayoutRoot_Loaded">
|
||||
<InkPresenter x:Name="_surface" Background="Black"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace STPSLDemo
|
||||
{
|
||||
public partial class UsageHistoryControl : UserControl
|
||||
{
|
||||
private const int _squareWidth = 12;
|
||||
private const int maxLastValuesCount = 2000;
|
||||
private const int _shiftStep = 3;
|
||||
|
||||
private int _shift = 0;
|
||||
|
||||
private int[] lastValues1 = new int[maxLastValuesCount];
|
||||
private int[] lastValues2 = new int[maxLastValuesCount];
|
||||
private int nextValueIndex;
|
||||
private int lastValuesCount;
|
||||
|
||||
private int max = 100;
|
||||
private int min = 0;
|
||||
|
||||
public UsageHistoryControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
lastValues1.Initialize();
|
||||
lastValues2.Initialize();
|
||||
nextValueIndex = 0;
|
||||
lastValuesCount = 0;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Redraw();
|
||||
}
|
||||
|
||||
private void Redraw()
|
||||
{
|
||||
_surface.Strokes.Clear();
|
||||
|
||||
for (int i = 0; i <= Width + _squareWidth; i += _squareWidth)
|
||||
{
|
||||
int x = i - _shift;
|
||||
if (x>= 0 && x < Width)
|
||||
{
|
||||
DrawLine(Colors.Green, x, 0, x, (int) Height);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Height; i += _squareWidth)
|
||||
{
|
||||
DrawLine(Colors.Green, 0, i, (int)Width, i);
|
||||
}
|
||||
int startValueIndex = (nextValueIndex - 1 + maxLastValuesCount) % maxLastValuesCount;
|
||||
|
||||
int prevVal1 = GetRelativeValue(lastValues1[startValueIndex]);
|
||||
int prevVal2 = GetRelativeValue(lastValues2[startValueIndex]);
|
||||
|
||||
for (int i = 1; i < lastValuesCount; ++i)
|
||||
{
|
||||
int index = nextValueIndex - 1 - i;
|
||||
if (index < 0)
|
||||
{
|
||||
index += maxLastValuesCount;
|
||||
}
|
||||
|
||||
int val1 = GetRelativeValue(lastValues1[index]);
|
||||
int val2 = GetRelativeValue(lastValues2[index]);
|
||||
|
||||
//Brush redBrush =
|
||||
// new LinearGradientBrush(
|
||||
// new Point(0, -(int)Height / 2),
|
||||
// new Point(0, (int)Height),
|
||||
// Color.Black,
|
||||
// Color.Red);
|
||||
|
||||
DrawLine(
|
||||
Colors.Red,
|
||||
(int)Width - (i - 1) * _shiftStep, (int)Height - prevVal2,
|
||||
(int)Width - i * _shiftStep, (int)Height - val2);
|
||||
|
||||
//g.FillPolygon(
|
||||
// redBrush,
|
||||
// new Point[]
|
||||
// {
|
||||
// new Point((int)Width-(i-1)*_shiftStep, (int)Height-prevVal2),
|
||||
// new Point((int)Width-i*_shiftStep, (int)Height-val2),
|
||||
// new Point((int)Width-i*_shiftStep, (int)Height),
|
||||
// new Point((int)Width-(i-1)*_shiftStep, (int)Height),
|
||||
// });
|
||||
|
||||
//Brush greenBrush =
|
||||
// new LinearGradientBrush(
|
||||
// new Point(0, -(int)Height / 2),
|
||||
// new Point(0, (int)Height),
|
||||
// Color.Black,
|
||||
// Color.LawnGreen);
|
||||
|
||||
DrawLine(
|
||||
Color.FromArgb(255, 124, 252, 0), // Colors.LawnGreen
|
||||
(int)Width - (i - 1) * _shiftStep, (int)Height - prevVal1,
|
||||
(int)Width - i * _shiftStep, (int)Height - val1);
|
||||
|
||||
//g.FillPolygon(
|
||||
// greenBrush,
|
||||
// new Point[]
|
||||
// {
|
||||
// new Point((int)Width-(i-1)*_shiftStep, (int)Height-prevVal1),
|
||||
// new Point((int)Width-i*_shiftStep, (int)Height-val1),
|
||||
// new Point((int)Width-i*_shiftStep, (int)Height),
|
||||
// new Point((int)Width-(i-1)*_shiftStep, (int)Height),
|
||||
// });
|
||||
|
||||
prevVal1 = val1;
|
||||
prevVal2 = val2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int GetRelativeValue(int val)
|
||||
{
|
||||
int result = val * ((int)Height - 2) / max + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void AddValues(int val1, int val2)
|
||||
{
|
||||
lastValues1[nextValueIndex] = val1;
|
||||
lastValues2[nextValueIndex] = val2;
|
||||
|
||||
nextValueIndex++;
|
||||
nextValueIndex %= maxLastValuesCount;
|
||||
lastValuesCount++;
|
||||
if (lastValuesCount > maxLastValuesCount)
|
||||
{
|
||||
lastValuesCount = maxLastValuesCount;
|
||||
}
|
||||
|
||||
_shift += _shiftStep;
|
||||
_shift %= _squareWidth;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
// Make sure that the maximum value is never set lower than the minimum value.
|
||||
if (value < min)
|
||||
{
|
||||
min = value;
|
||||
}
|
||||
|
||||
max = value;
|
||||
|
||||
// Invalidate the control to get a repaint.
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLine(Color color, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
if (x1 < 0 || x2 < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DrawPolygon(color, new Point(x1, y1), new Point(x2, y2));
|
||||
}
|
||||
|
||||
private void DrawPolygon(
|
||||
Color color,
|
||||
params Point[] points)
|
||||
{
|
||||
StylusPointCollection stylusPointCollection = new StylusPointCollection();
|
||||
foreach (Point point in points)
|
||||
{
|
||||
stylusPointCollection.Add(new StylusPoint(point.X, point.Y));
|
||||
}
|
||||
|
||||
Stroke stroke = new Stroke(stylusPointCollection);
|
||||
|
||||
stroke.DrawingAttributes.Color = color;
|
||||
stroke.DrawingAttributes.Width = 1;
|
||||
stroke.DrawingAttributes.Height = 1;
|
||||
|
||||
_surface.Strokes.Add(stroke);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -65,6 +65,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
@@ -89,16 +90,6 @@
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
||||
<Reference Include="System">
|
||||
@@ -120,6 +111,7 @@
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TestParallelMethods.cs" />
|
||||
<Compile Include="TestFalseFillStateWithParams.cs" />
|
||||
<Compile Include="TestFillStateWithParams.cs" />
|
||||
<Compile Include="TestWIGFillStateWithParams.cs" />
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
using Amib.Threading;
|
||||
|
||||
namespace SmartThreadPoolTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for TestParallelMethods.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
[Category("TestParallelMethods")]
|
||||
public class TestParallelMethods
|
||||
{
|
||||
[Test]
|
||||
public void TestJoin()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
SafeCounter sc = new SafeCounter();
|
||||
|
||||
stp.Join(
|
||||
sc.Increment,
|
||||
sc.Increment,
|
||||
sc.Increment);
|
||||
|
||||
Assert.AreEqual(3, sc.Counter);
|
||||
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
sc.Reset();
|
||||
|
||||
Action[] actions = new Action[1000];
|
||||
for (int i = 0; i < actions.Length; i++)
|
||||
{
|
||||
actions[i] = sc.Increment;
|
||||
}
|
||||
|
||||
stp.Join(actions);
|
||||
|
||||
Assert.AreEqual(actions.Length, sc.Counter);
|
||||
}
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
private class SafeCounter
|
||||
{
|
||||
private int _counter;
|
||||
|
||||
public void Increment()
|
||||
{
|
||||
Interlocked.Increment(ref _counter);
|
||||
}
|
||||
|
||||
public int Counter
|
||||
{
|
||||
get { return _counter; }
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestChoice()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
int index = stp.Choice(
|
||||
() => Thread.Sleep(1000),
|
||||
() => Thread.Sleep(1500),
|
||||
() => Thread.Sleep(500));
|
||||
|
||||
Assert.AreEqual(2, index);
|
||||
|
||||
index = stp.Choice(
|
||||
() => Thread.Sleep(300),
|
||||
() => Thread.Sleep(100),
|
||||
() => Thread.Sleep(200));
|
||||
|
||||
Assert.AreEqual(1, index);
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPipe()
|
||||
{
|
||||
SafeCounter sc = new SafeCounter();
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
stp.Pipe(
|
||||
sc,
|
||||
sc1 => { if (sc.Counter == 0) { sc1.Increment(); }},
|
||||
sc1 => { if (sc.Counter == 1) { sc1.Increment(); }},
|
||||
sc1 => { if (sc.Counter == 2) { sc1.Increment(); }}
|
||||
);
|
||||
|
||||
Assert.AreEqual(3, sc.Counter);
|
||||
|
||||
stp.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using NUnit.Framework;
|
||||
@@ -73,11 +72,10 @@ namespace SmartThreadPoolTests
|
||||
|
||||
stp.Start();
|
||||
|
||||
Assert.IsTrue(wig.WaitForIdle(200));
|
||||
Assert.IsTrue(stp.WaitForIdle(0));
|
||||
Assert.IsTrue(wig.WaitForIdle(5000), "WIG is not idle");
|
||||
Assert.IsTrue(stp.WaitForIdle(5000), "STP is not idle");
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TwoWIGsStartSuspended()
|
||||
{
|
||||
|
||||
@@ -18,30 +18,37 @@ namespace SmartThreadPoolTests
|
||||
[Test]
|
||||
public void TestDefaultPriority()
|
||||
{
|
||||
SmartThreadPool stp = new SmartThreadPool();
|
||||
|
||||
IWorkItemResult wir = stp.QueueWorkItem(new WorkItemCallback(DoSomeWork));
|
||||
ThreadPriority currentThreadPriority = (ThreadPriority)wir.GetResult();
|
||||
|
||||
Assert.AreEqual(currentThreadPriority, SmartThreadPool.DefaultThreadPriority);
|
||||
CheckSinglePriority(SmartThreadPool.DefaultThreadPriority);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPriorities()
|
||||
public void TestLowestPriority()
|
||||
{
|
||||
ThreadPriority [] priorities =
|
||||
{
|
||||
ThreadPriority.Lowest,
|
||||
ThreadPriority.BelowNormal,
|
||||
ThreadPriority.Normal,
|
||||
ThreadPriority.AboveNormal,
|
||||
ThreadPriority.Highest,
|
||||
};
|
||||
CheckSinglePriority(ThreadPriority.Lowest);
|
||||
}
|
||||
|
||||
foreach(ThreadPriority priority in priorities)
|
||||
{
|
||||
CheckSinglePriority(priority);
|
||||
}
|
||||
[Test]
|
||||
public void TestBelowNormalPriority()
|
||||
{
|
||||
CheckSinglePriority(ThreadPriority.BelowNormal);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNormalPriority()
|
||||
{
|
||||
CheckSinglePriority(ThreadPriority.BelowNormal);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAboveNormalPriority()
|
||||
{
|
||||
CheckSinglePriority(ThreadPriority.AboveNormal);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHighestPriority()
|
||||
{
|
||||
CheckSinglePriority(ThreadPriority.Highest);
|
||||
}
|
||||
|
||||
private void CheckSinglePriority(ThreadPriority threadPriority)
|
||||
@@ -51,13 +58,13 @@ namespace SmartThreadPoolTests
|
||||
|
||||
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
IWorkItemResult wir = stp.QueueWorkItem(new WorkItemCallback(DoSomeWork));
|
||||
IWorkItemResult wir = stp.QueueWorkItem(new WorkItemCallback(GetThreadPriority));
|
||||
ThreadPriority currentThreadPriority = (ThreadPriority)wir.GetResult();
|
||||
|
||||
Assert.AreEqual(currentThreadPriority, threadPriority);
|
||||
Assert.AreEqual(threadPriority, currentThreadPriority);
|
||||
}
|
||||
|
||||
private object DoSomeWork(object state)
|
||||
private object GetThreadPriority(object state)
|
||||
{
|
||||
return Thread.CurrentThread.Priority;
|
||||
}
|
||||
|
||||
@@ -152,5 +152,23 @@ namespace WorkItemsGroupTests
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitForIdleEvent()
|
||||
{
|
||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(1);
|
||||
ManualResetEvent wigIsIdle = new ManualResetEvent(false);
|
||||
|
||||
workItemsGroup.OnIdle += wig => wigIsIdle.Set();
|
||||
|
||||
workItemsGroup.QueueWorkItem(() => { });
|
||||
|
||||
bool eventFired = wigIsIdle.WaitOne(100, true);
|
||||
|
||||
smartThreadPool.Shutdown();
|
||||
|
||||
Assert.IsTrue(eventFired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,24 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkItemsGroupDemo", "WorkI
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPCEDemo", "STPCEDemo\STPCEDemo.csproj", "{356114BA-5F10-4DB6-9971-987CE11F765F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartThreadPoolSL", "SmartThreadPool\SmartThreadPoolSL.csproj", "{A6590A96-22B3-4889-B80E-2C398810E441}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPSLDemo", "STPSLDemo\STPSLDemo.csproj", "{44EE4F12-169F-4949-91F7-EFC7100C8BE5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartThreadPoolMono", "SmartThreadPool\SmartThreadPoolMono.csproj", "{3462F30B-0156-409C-B256-6046D6F1764B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CE", "CE", "{655817E0-5892-4E47-9598-A5AB25B9B64D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Silverlight", "Silverlight", "{EAF99021-123A-4E2F-9039-85003559100B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono", "Mono", "{9C6E9536-59A0-4F06-8085-0BB30ECB5158}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSmartThreadPoolMono", "TestSmartThreadPool\TestSmartThreadPoolMono.csproj", "{E8C4E483-0336-4D89-95F8-8924789ACA51}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B0D5FBC5-E0A7-43C1-83E0-AC6B9224ADB6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C89D3C93-9BBC-47B9-943F-6962AACBE534}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -25,7 +43,6 @@ Global
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
@@ -54,12 +71,39 @@ Global
|
||||
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{A6590A96-22B3-4889-B80E-2C398810E441}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6590A96-22B3-4889-B80E-2C398810E441}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6590A96-22B3-4889-B80E-2C398810E441}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6590A96-22B3-4889-B80E-2C398810E441}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{44EE4F12-169F-4949-91F7-EFC7100C8BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{44EE4F12-169F-4949-91F7-EFC7100C8BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{44EE4F12-169F-4949-91F7-EFC7100C8BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{44EE4F12-169F-4949-91F7-EFC7100C8BE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3462F30B-0156-409C-B256-6046D6F1764B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3462F30B-0156-409C-B256-6046D6F1764B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3462F30B-0156-409C-B256-6046D6F1764B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3462F30B-0156-409C-B256-6046D6F1764B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E8C4E483-0336-4D89-95F8-8924789ACA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E8C4E483-0336-4D89-95F8-8924789ACA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E8C4E483-0336-4D89-95F8-8924789ACA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E8C4E483-0336-4D89-95F8-8924789ACA51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{356114BA-5F10-4DB6-9971-987CE11F765F} = {655817E0-5892-4E47-9598-A5AB25B9B64D}
|
||||
{D81DD596-C71F-4AC2-816C-63C19589E7E0} = {655817E0-5892-4E47-9598-A5AB25B9B64D}
|
||||
{976DB12F-9198-4AD9-981A-1652615C9B0D} = {B0D5FBC5-E0A7-43C1-83E0-AC6B9224ADB6}
|
||||
{C11A4561-CCB5-4C96-8DF2-B804031D89D8} = {B0D5FBC5-E0A7-43C1-83E0-AC6B9224ADB6}
|
||||
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD} = {B0D5FBC5-E0A7-43C1-83E0-AC6B9224ADB6}
|
||||
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3} = {B0D5FBC5-E0A7-43C1-83E0-AC6B9224ADB6}
|
||||
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03} = {C89D3C93-9BBC-47B9-943F-6962AACBE534}
|
||||
{44EE4F12-169F-4949-91F7-EFC7100C8BE5} = {EAF99021-123A-4E2F-9039-85003559100B}
|
||||
{A6590A96-22B3-4889-B80E-2C398810E441} = {EAF99021-123A-4E2F-9039-85003559100B}
|
||||
{3462F30B-0156-409C-B256-6046D6F1764B} = {9C6E9536-59A0-4F06-8085-0BB30ECB5158}
|
||||
{E8C4E483-0336-4D89-95F8-8924789ACA51} = {9C6E9536-59A0-4F06-8085-0BB30ECB5158}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Amib.Threading.Internal
|
||||
/// It uses the WaitForMultipleObjects API to do the WaitAll and WaitAny.
|
||||
/// Note that this class doesn't even inherit from WaitHandle!
|
||||
/// </summary>
|
||||
public class EventWaitHandle
|
||||
public class STPEventWaitHandle
|
||||
{
|
||||
#region Public Constants
|
||||
|
||||
@@ -31,6 +31,11 @@ namespace Amib.Threading.Internal
|
||||
|
||||
#region WaitAll and WaitAny
|
||||
|
||||
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
||||
}
|
||||
|
||||
private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles)
|
||||
{
|
||||
IntPtr[] nativeHandles = new IntPtr[waitHandles.Length];
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Amib.Threading
|
||||
}
|
||||
|
||||
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
/// <summary>
|
||||
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Amib.Threading.Internal
|
||||
@@ -22,7 +23,7 @@ namespace Amib.Threading.Internal
|
||||
/// <summary>
|
||||
/// Work items queues. There is one for each type of priority
|
||||
/// </summary>
|
||||
private readonly Queue [] _queues = new Queue[_queuesCount];
|
||||
private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount];
|
||||
|
||||
/// <summary>
|
||||
/// The total number of work items within the queues
|
||||
@@ -42,7 +43,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
for(int i = 0; i < _queues.Length; ++i)
|
||||
{
|
||||
_queues[i] = new Queue();
|
||||
_queues[i] = new LinkedList<IHasWorkItemPriority>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ namespace Amib.Threading.Internal
|
||||
Debug.Assert(queueIndex >= 0);
|
||||
Debug.Assert(queueIndex < _queuesCount);
|
||||
|
||||
_queues[queueIndex].Enqueue(workItem);
|
||||
_queues[queueIndex].AddLast(workItem);
|
||||
++_workItemsCount;
|
||||
++_version;
|
||||
}
|
||||
@@ -79,7 +80,8 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
int queueIndex = GetNextNonEmptyQueue(-1);
|
||||
Debug.Assert(queueIndex >= 0);
|
||||
workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority;
|
||||
workItem = _queues[queueIndex].First.Value;
|
||||
_queues[queueIndex].RemoveFirst();
|
||||
Debug.Assert(null != workItem);
|
||||
--_workItemsCount;
|
||||
++_version;
|
||||
@@ -125,7 +127,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
if (_workItemsCount > 0)
|
||||
{
|
||||
foreach(Queue queue in _queues)
|
||||
foreach(LinkedList<IHasWorkItemPriority> queue in _queues)
|
||||
{
|
||||
queue.Clear();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
[assembly: Guid("c764a3de-c4f8-434d-85b5-a09830d1e44f")]
|
||||
[assembly: AssemblyVersion("2.0.1.0")]
|
||||
[assembly: AssemblyVersion("2.2.0.0")]
|
||||
[assembly: InternalsVisibleTo("STPTests")]
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#if SILVERLIGHT
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace Amib.Threading
|
||||
{
|
||||
public enum ThreadPriority
|
||||
{
|
||||
Lowest,
|
||||
BelowNormal,
|
||||
Normal,
|
||||
AboveNormal,
|
||||
Highest,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#if !(WindowsCE)
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Amib.Threading.Internal
|
||||
{
|
||||
#if _WINDOWS
|
||||
internal static class STPEventWaitHandle
|
||||
{
|
||||
public const int WaitTimeout = Timeout.Infinite;
|
||||
|
||||
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout);
|
||||
}
|
||||
|
||||
internal static int WaitAny(WaitHandle[] waitHandles)
|
||||
{
|
||||
return WaitHandle.WaitAny(waitHandles);
|
||||
}
|
||||
|
||||
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout);
|
||||
}
|
||||
|
||||
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return waitHandle.WaitOne(millisecondsTimeout);
|
||||
}
|
||||
}
|
||||
#else
|
||||
internal static class STPEventWaitHandle
|
||||
{
|
||||
public const int WaitTimeout = Timeout.Infinite;
|
||||
|
||||
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||
}
|
||||
|
||||
internal static int WaitAny(WaitHandle[] waitHandles)
|
||||
{
|
||||
return WaitHandle.WaitAny(waitHandles);
|
||||
}
|
||||
|
||||
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||
}
|
||||
|
||||
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||
{
|
||||
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,17 @@
|
||||
using System;
|
||||
#if !(WindowsCE)
|
||||
|
||||
using System.Diagnostics;
|
||||
#endif
|
||||
using System.Threading;
|
||||
|
||||
namespace Amib.Threading
|
||||
{
|
||||
public interface ISTPPerformanceCountersReader
|
||||
{
|
||||
long InUseThreads { get; }
|
||||
long ActiveThreads { get; }
|
||||
long WorkItemsQueued { get; }
|
||||
long WorkItemsProcessed { get; }
|
||||
}
|
||||
}
|
||||
|
||||
namespace Amib.Threading.Internal
|
||||
{
|
||||
@@ -14,7 +23,7 @@ namespace Amib.Threading.Internal
|
||||
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
||||
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
||||
}
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
|
||||
internal enum STPPerformanceCounterType
|
||||
{
|
||||
@@ -347,7 +356,7 @@ namespace Amib.Threading.Internal
|
||||
}
|
||||
#endif
|
||||
|
||||
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters
|
||||
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
|
||||
{
|
||||
private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters();
|
||||
|
||||
@@ -363,5 +372,77 @@ namespace Amib.Threading.Internal
|
||||
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
|
||||
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
||||
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
||||
public long InUseThreads
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public long ActiveThreads
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public long WorkItemsQueued
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public long WorkItemsProcessed
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
}
|
||||
|
||||
internal class LocalSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
|
||||
{
|
||||
public void Close() { }
|
||||
public void Dispose() { }
|
||||
|
||||
private long _activeThreads;
|
||||
private long _inUseThreads;
|
||||
private long _workItemsQueued;
|
||||
private long _workItemsProcessed;
|
||||
|
||||
public long InUseThreads
|
||||
{
|
||||
get { return _inUseThreads; }
|
||||
}
|
||||
|
||||
public long ActiveThreads
|
||||
{
|
||||
get { return _activeThreads; }
|
||||
}
|
||||
|
||||
public long WorkItemsQueued
|
||||
{
|
||||
get { return _workItemsQueued; }
|
||||
}
|
||||
|
||||
public long WorkItemsProcessed
|
||||
{
|
||||
get { return _workItemsProcessed; }
|
||||
}
|
||||
|
||||
public void SampleThreads(long activeThreads, long inUseThreads)
|
||||
{
|
||||
_activeThreads = activeThreads;
|
||||
_inUseThreads = inUseThreads;
|
||||
}
|
||||
|
||||
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
|
||||
{
|
||||
_workItemsQueued = workItemsQueued;
|
||||
_workItemsProcessed = workItemsProcessed;
|
||||
}
|
||||
|
||||
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
|
||||
{
|
||||
// Not supported
|
||||
}
|
||||
|
||||
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
|
||||
{
|
||||
// Not supported
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,12 @@ namespace Amib.Threading
|
||||
/// </summary>
|
||||
public class STPStartInfo : WIGStartInfo
|
||||
{
|
||||
private int _idleTimeout;
|
||||
private int _minWorkerThreads;
|
||||
private int _maxWorkerThreads;
|
||||
private ThreadPriority _threadPriority;
|
||||
private string _performanceCounterInstanceName;
|
||||
private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
||||
private int _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
||||
private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
||||
private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority;
|
||||
private string _performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
||||
private bool _enableLocalPerformanceCounters;
|
||||
|
||||
public STPStartInfo()
|
||||
{
|
||||
@@ -31,6 +32,7 @@ namespace Amib.Threading
|
||||
_maxWorkerThreads = stpStartInfo.MaxWorkerThreads;
|
||||
_threadPriority = stpStartInfo.ThreadPriority;
|
||||
_performanceCounterInstanceName = stpStartInfo.PerformanceCounterInstanceName;
|
||||
_enableLocalPerformanceCounters = stpStartInfo._enableLocalPerformanceCounters;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +107,22 @@ namespace Amib.Threading
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable/Disable the local performance counter.
|
||||
/// This enables the user to get some performance information about the SmartThreadPool
|
||||
/// without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.)
|
||||
/// The default is false.
|
||||
/// </summary>
|
||||
public virtual bool EnableLocalPerformanceCounters
|
||||
{
|
||||
get { return _enableLocalPerformanceCounters; }
|
||||
set
|
||||
{
|
||||
ThrowIfReadOnly();
|
||||
_enableLocalPerformanceCounters = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a readonly version of this STPStartInfo.
|
||||
/// </summary>
|
||||
@@ -113,143 +131,5 @@ namespace Amib.Threading
|
||||
{
|
||||
return new STPStartInfo(this) { _readOnly = true };
|
||||
}
|
||||
/*
|
||||
#region STPStartInfoRO class
|
||||
|
||||
private class STPStartInfoRO : STPStartInfo
|
||||
{
|
||||
private readonly STPStartInfo _stpStartInfo;
|
||||
|
||||
public STPStartInfoRO(STPStartInfo stpStartInfo)
|
||||
{
|
||||
_stpStartInfo = stpStartInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the idle timeout in milliseconds.
|
||||
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
|
||||
/// </summary>
|
||||
public override int IdleTimeout
|
||||
{
|
||||
get { return _stpStartInfo.IdleTimeout; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the lower limit of threads in the pool.
|
||||
/// </summary>
|
||||
public override int MinWorkerThreads
|
||||
{
|
||||
get { return _stpStartInfo.MinWorkerThreads; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the upper limit of threads in the pool.
|
||||
/// </summary>
|
||||
public override int MaxWorkerThreads
|
||||
{
|
||||
get { return _stpStartInfo.MaxWorkerThreads; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scheduling priority of the threads in the pool.
|
||||
/// The Os handles the scheduling.
|
||||
/// </summary>
|
||||
public override ThreadPriority ThreadPriority
|
||||
{
|
||||
get { return _stpStartInfo.ThreadPriority; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the performance counter instance name of this SmartThreadPool
|
||||
/// The default is null which indicate not to use performance counters at all.
|
||||
/// </summary>
|
||||
public override string PerformanceCounterInstanceName
|
||||
{
|
||||
get { return _stpStartInfo.PerformanceCounterInstanceName; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to use the caller's security context
|
||||
/// </summary>
|
||||
public override bool UseCallerCallContext
|
||||
{
|
||||
get { return _stpStartInfo.UseCallerCallContext; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to use the caller's HTTP context
|
||||
/// </summary>
|
||||
public override bool UseCallerHttpContext
|
||||
{
|
||||
get { return _stpStartInfo.UseCallerHttpContext; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to dispose of the state object of a work item
|
||||
/// </summary>
|
||||
public override bool DisposeOfStateObjects
|
||||
{
|
||||
get { return _stpStartInfo.DisposeOfStateObjects; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the run the post execute options
|
||||
/// </summary>
|
||||
public override CallToPostExecute CallToPostExecute
|
||||
{
|
||||
get { return _stpStartInfo.CallToPostExecute; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default post execute callback
|
||||
/// </summary>
|
||||
public override PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||
{
|
||||
get { return _stpStartInfo.PostExecuteWorkItemCallback; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if the work items execution should be suspended until the Start()
|
||||
/// method is called.
|
||||
/// </summary>
|
||||
public override bool StartSuspended
|
||||
{
|
||||
get { return _stpStartInfo.StartSuspended; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default priority that a work item gets when it is enqueued
|
||||
/// </summary>
|
||||
public override WorkItemPriority WorkItemPriority
|
||||
{
|
||||
get { return _stpStartInfo.WorkItemPriority; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if QueueWorkItem of Action<...>/Func<...> fill the
|
||||
/// arguments as an object array into the state of the work item.
|
||||
/// The arguments can be access later by IWorkItemResult.State.
|
||||
/// </summary>
|
||||
public override bool FillStateWithArgs
|
||||
{
|
||||
get { return _stpStartInfo.FillStateWithArgs; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,13 @@
|
||||
// - Added IsIdle flag to the SmartThreadPool and IWorkItemsGroup
|
||||
// - Added support for WinCE
|
||||
// - Added support for Action<T> and Func<T>
|
||||
//
|
||||
// 07 April 2009 - Changes:
|
||||
// - Added support for Silverlight and Mono
|
||||
// - Added Join, Choice, and Pipe to SmartThreadPool.
|
||||
// - Added local performance counters (for Mono, Silverlight, and WindowsCE)
|
||||
// - Changed duration measures from DateTime.Now to Stopwatch.
|
||||
// - Queues changed from System.Collections.Queue to System.Collections.Generic.LinkedList<T>.
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -71,6 +78,7 @@ using System;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
@@ -172,7 +180,7 @@ namespace Amib.Threading
|
||||
/// Count the work items handled.
|
||||
/// Used by the performance counter.
|
||||
/// </summary>
|
||||
private long _workItemsProcessed;
|
||||
private int _workItemsProcessed;
|
||||
|
||||
/// <summary>
|
||||
/// Number of threads that currently work (not idle).
|
||||
@@ -244,9 +252,14 @@ namespace Amib.Threading
|
||||
private CanceledWorkItemsGroup _canceledSmartThreadPool = new CanceledWorkItemsGroup();
|
||||
|
||||
/// <summary>
|
||||
/// STP performance counters
|
||||
/// Windows STP performance counters
|
||||
/// </summary>
|
||||
private ISTPInstancePerformanceCounters _pcs = NullSTPInstancePerformanceCounters.Instance;
|
||||
private ISTPInstancePerformanceCounters _windowsPCs = NullSTPInstancePerformanceCounters.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Local STP performance counters
|
||||
/// </summary>
|
||||
private ISTPInstancePerformanceCounters _localPCs = NullSTPInstancePerformanceCounters.Instance;
|
||||
|
||||
|
||||
#if (WindowsCE)
|
||||
@@ -382,28 +395,32 @@ namespace Amib.Threading
|
||||
|
||||
_isSuspended = _stpStartInfo.StartSuspended;
|
||||
|
||||
#if (WindowsCE)
|
||||
#if (WindowsCE) || (SILVERLIGHT)
|
||||
if (null != _stpStartInfo.PerformanceCounterInstanceName)
|
||||
{
|
||||
throw new NotSupportedException("Performance counters are not implemented for Compact Framework");
|
||||
throw new NotSupportedException("Performance counters are not implemented for Compact Framework/Silverlight");
|
||||
}
|
||||
|
||||
#else
|
||||
if (null != _stpStartInfo.PerformanceCounterInstanceName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_pcs = new STPInstancePerformanceCounters(_stpStartInfo.PerformanceCounterInstanceName);
|
||||
_windowsPCs = new STPInstancePerformanceCounters(_stpStartInfo.PerformanceCounterInstanceName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine("Unable to create Performance Counters: " + e);
|
||||
_pcs = NullSTPInstancePerformanceCounters.Instance;
|
||||
_windowsPCs = NullSTPInstancePerformanceCounters.Instance;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the STP is not started suspended then start the threads.
|
||||
if (_stpStartInfo.EnableLocalPerformanceCounters)
|
||||
{
|
||||
_localPCs = new LocalSTPInstancePerformanceCounters();
|
||||
}
|
||||
|
||||
// If the STP is not started suspended then start the threads.
|
||||
if (!_isSuspended)
|
||||
{
|
||||
StartOptimalNumberOfThreads();
|
||||
@@ -493,7 +510,8 @@ namespace Amib.Threading
|
||||
|
||||
private void IncrementWorkItemsCount()
|
||||
{
|
||||
_pcs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
_windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
_localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
|
||||
int count = Interlocked.Increment(ref _currentWorkItemsCount);
|
||||
//Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
|
||||
@@ -506,21 +524,23 @@ namespace Amib.Threading
|
||||
|
||||
private void DecrementWorkItemsCount()
|
||||
{
|
||||
++_workItemsProcessed;
|
||||
int count = Interlocked.Decrement(ref _currentWorkItemsCount);
|
||||
//Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
|
||||
if (count == 0)
|
||||
{
|
||||
IsIdle = true;
|
||||
_isIdleWaitHandle.Set();
|
||||
}
|
||||
|
||||
Interlocked.Increment(ref _workItemsProcessed);
|
||||
|
||||
if (!_shutdown)
|
||||
{
|
||||
// The counter counts even if the work item was cancelled
|
||||
_pcs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
_windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
_localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
|
||||
}
|
||||
|
||||
int count = Interlocked.Decrement(ref _currentWorkItemsCount);
|
||||
//Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
|
||||
if (count == 0)
|
||||
{
|
||||
IsIdle = true;
|
||||
_isIdleWaitHandle.Set();
|
||||
}
|
||||
}
|
||||
|
||||
internal void RegisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
|
||||
@@ -548,7 +568,8 @@ namespace Amib.Threading
|
||||
if (_workerThreads.Contains(Thread.CurrentThread))
|
||||
{
|
||||
_workerThreads.Remove(Thread.CurrentThread);
|
||||
_pcs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
_windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
_localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,14 +606,17 @@ namespace Amib.Threading
|
||||
// Configure the new thread and start it
|
||||
workerThread.Name = "STP " + Name + " Thread #" + _threadCounter;
|
||||
workerThread.IsBackground = true;
|
||||
workerThread.Priority = _stpStartInfo.ThreadPriority;
|
||||
#if !(SILVERLIGHT)
|
||||
workerThread.Priority = _stpStartInfo.ThreadPriority;
|
||||
#endif
|
||||
workerThread.Start();
|
||||
++_threadCounter;
|
||||
|
||||
// Add it to the dictionary and update its creation time.
|
||||
_workerThreads[workerThread] = new ThreadEntry(this);
|
||||
|
||||
_pcs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
_windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
_localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -704,7 +728,8 @@ namespace Amib.Threading
|
||||
// Execute the callback. Make sure to accurately
|
||||
// record how many callbacks are currently executing.
|
||||
int inUseWorkerThreads = Interlocked.Increment(ref _inUseWorkerThreads);
|
||||
_pcs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
_windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
_localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
|
||||
// Mark that the _inUseWorkerThreads incremented, so in the finally{}
|
||||
// statement we will decrement it correctly.
|
||||
@@ -733,7 +758,8 @@ namespace Amib.Threading
|
||||
if (bInUseWorkerThreadsWasIncremented)
|
||||
{
|
||||
int inUseWorkerThreads = Interlocked.Decrement(ref _inUseWorkerThreads);
|
||||
_pcs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
_windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
_localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
|
||||
}
|
||||
|
||||
// Notify that the work item has been completed.
|
||||
@@ -749,8 +775,8 @@ namespace Amib.Threading
|
||||
catch(ThreadAbortException tae)
|
||||
{
|
||||
tae.GetHashCode();
|
||||
// Handle the abort exception gracfully.
|
||||
#if !(WindowsCE)
|
||||
// Handle the abort exception gracfully.
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
Thread.ResetAbort();
|
||||
#endif
|
||||
}
|
||||
@@ -767,14 +793,16 @@ namespace Amib.Threading
|
||||
|
||||
private void ExecuteWorkItem(WorkItem workItem)
|
||||
{
|
||||
_pcs.SampleWorkItemsWaitTime(workItem.WaitingTime);
|
||||
_windowsPCs.SampleWorkItemsWaitTime(workItem.WaitingTime);
|
||||
_localPCs.SampleWorkItemsWaitTime(workItem.WaitingTime);
|
||||
try
|
||||
{
|
||||
workItem.Execute();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pcs.SampleWorkItemsProcessTime(workItem.ProcessTime);
|
||||
_windowsPCs.SampleWorkItemsProcessTime(workItem.ProcessTime);
|
||||
_localPCs.SampleWorkItemsProcessTime(workItem.ProcessTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +811,6 @@ namespace Amib.Threading
|
||||
|
||||
#region Public Methods
|
||||
|
||||
|
||||
private void ValidateWaitForIdle()
|
||||
{
|
||||
if (null != CurrentThreadEntry && CurrentThreadEntry.AssociatedSmartThreadPool == this)
|
||||
@@ -844,13 +871,13 @@ namespace Amib.Threading
|
||||
{
|
||||
ValidateNotDisposed();
|
||||
|
||||
ISTPInstancePerformanceCounters pcs = _pcs;
|
||||
ISTPInstancePerformanceCounters pcs = _windowsPCs;
|
||||
|
||||
if (NullSTPInstancePerformanceCounters.Instance != _pcs)
|
||||
if (NullSTPInstancePerformanceCounters.Instance != _windowsPCs)
|
||||
{
|
||||
// Set the _pcs to "null" to stop updating the performance
|
||||
// counters
|
||||
_pcs = NullSTPInstancePerformanceCounters.Instance;
|
||||
_windowsPCs = NullSTPInstancePerformanceCounters.Instance;
|
||||
|
||||
pcs.Dispose();
|
||||
}
|
||||
@@ -871,7 +898,8 @@ namespace Amib.Threading
|
||||
}
|
||||
|
||||
int millisecondsLeft = millisecondsTimeout;
|
||||
DateTime start = DateTime.Now;
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
//DateTime start = DateTime.UtcNow;
|
||||
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
|
||||
bool timeout = false;
|
||||
|
||||
@@ -896,8 +924,8 @@ namespace Amib.Threading
|
||||
if(!waitInfinitely)
|
||||
{
|
||||
// Update the time left to wait
|
||||
TimeSpan ts = DateTime.Now - start;
|
||||
millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
|
||||
//TimeSpan ts = DateTime.UtcNow - start;
|
||||
millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,7 +943,7 @@ namespace Amib.Threading
|
||||
{
|
||||
try
|
||||
{
|
||||
thread.Abort("Shutdown");
|
||||
thread.Abort(); // Shutdown
|
||||
}
|
||||
catch(SecurityException e)
|
||||
{
|
||||
@@ -1323,6 +1351,20 @@ namespace Amib.Threading
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsShuttingdown
|
||||
{
|
||||
get { return _shutdown; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the local calculated performance counters
|
||||
/// Available only if STPStartInfo.EnableLocalPerformanceCounters is true.
|
||||
/// </summary>
|
||||
public ISTPPerformanceCountersReader PerformanceCountersReader
|
||||
{
|
||||
get { return (ISTPPerformanceCountersReader)_localPCs; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
@@ -1460,7 +1502,7 @@ namespace Amib.Threading
|
||||
public override bool WaitForIdle(int millisecondsTimeout)
|
||||
{
|
||||
ValidateWaitForIdle();
|
||||
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
||||
return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1489,6 +1531,109 @@ namespace Amib.Threading
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Join, Choice, Pipe, etc.
|
||||
|
||||
/// <summary>
|
||||
/// Executes all actions in parallel.
|
||||
/// Returns when they all finish.
|
||||
/// </summary>
|
||||
/// <param name="actions">Actions to execute</param>
|
||||
public void Join(IEnumerable<Action> actions)
|
||||
{
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo { StartSuspended = true };
|
||||
IWorkItemsGroup workItemsGroup = CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
foreach (Action action in actions)
|
||||
{
|
||||
workItemsGroup.QueueWorkItem(action);
|
||||
}
|
||||
workItemsGroup.Start();
|
||||
workItemsGroup.WaitForIdle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes all actions in parallel.
|
||||
/// Returns when they all finish.
|
||||
/// </summary>
|
||||
/// <param name="actions">Actions to execute</param>
|
||||
public void Join(params Action[] actions)
|
||||
{
|
||||
Join((IEnumerable<Action>)actions);
|
||||
}
|
||||
|
||||
private class ChoiceIndex
|
||||
{
|
||||
public int _index = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes all actions in parallel
|
||||
/// Returns when the first one completes
|
||||
/// </summary>
|
||||
/// <param name="actions">Actions to execute</param>
|
||||
public int Choice(IEnumerable<Action> actions)
|
||||
{
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo { StartSuspended = true };
|
||||
IWorkItemsGroup workItemsGroup = CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
|
||||
ManualResetEvent anActionCompleted = new ManualResetEvent(false);
|
||||
|
||||
ChoiceIndex choiceIndex = new ChoiceIndex();
|
||||
|
||||
int i = 0;
|
||||
foreach (Action action in actions)
|
||||
{
|
||||
Action act = action;
|
||||
int value = i;
|
||||
workItemsGroup.QueueWorkItem(() => { act(); Interlocked.CompareExchange(ref choiceIndex._index, value, -1); anActionCompleted.Set(); });
|
||||
++i;
|
||||
}
|
||||
workItemsGroup.Start();
|
||||
anActionCompleted.WaitOne();
|
||||
|
||||
return choiceIndex._index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes all actions in parallel
|
||||
/// Returns when the first one completes
|
||||
/// </summary>
|
||||
/// <param name="actions">Actions to execute</param>
|
||||
public int Choice(params Action[] actions)
|
||||
{
|
||||
return Choice((IEnumerable<Action>)actions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes actions in sequence asynchronously.
|
||||
/// Returns immediately.
|
||||
/// </summary>
|
||||
/// <param name="pipeState">A state context that passes </param>
|
||||
/// <param name="actions">Actions to execute in the order they should run</param>
|
||||
public void Pipe<T>(T pipeState, IEnumerable<Action<T>> actions)
|
||||
{
|
||||
WIGStartInfo wigStartInfo = new WIGStartInfo { StartSuspended = true };
|
||||
IWorkItemsGroup workItemsGroup = CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
|
||||
foreach (Action<T> action in actions)
|
||||
{
|
||||
Action<T> act = action;
|
||||
workItemsGroup.QueueWorkItem(() => act(pipeState));
|
||||
}
|
||||
workItemsGroup.Start();
|
||||
workItemsGroup.WaitForIdle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes actions in sequence asynchronously.
|
||||
/// Returns immediately.
|
||||
/// </summary>
|
||||
/// <param name="pipeState"></param>
|
||||
/// <param name="actions">Actions to execute in the order they should run</param>
|
||||
public void Pipe<T>(T pipeState, params Action<T>[] actions)
|
||||
{
|
||||
Pipe(pipeState, (IEnumerable<Action<T>>)actions);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>.\bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
@@ -26,21 +26,7 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugCE|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\DebugCE\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DefineConstants>TRACE;_WINDOWS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
@@ -59,6 +45,7 @@
|
||||
<Compile Include="PriorityQueue.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SmartThreadPool.cs" />
|
||||
<Compile Include="STPEventWaitHandle.cs" />
|
||||
<Compile Include="STPPerformanceCounter.cs" />
|
||||
<Compile Include="STPStartInfo.cs" />
|
||||
<Compile Include="SynchronizedDictionary.cs" />
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;WindowsCE,_WINDOWS</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
@@ -44,7 +44,7 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||
<DefineConstants>TRACE;WindowsCE,_WINDOWS</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
@@ -52,18 +52,6 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE;WindowsCE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
@@ -82,6 +70,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SmartThreadPool.cs" />
|
||||
<Compile Include="SmartThreadPool.ThreadEntry.cs" />
|
||||
<Compile Include="Stopwatch.cs" />
|
||||
<Compile Include="STPPerformanceCounter.cs" />
|
||||
<Compile Include="STPStartInfo.cs" />
|
||||
<Compile Include="SynchronizedDictionary.cs" />
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{3462F30B-0156-409C-B256-6046D6F1764B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<NoStandardLibraries>false</NoStandardLibraries>
|
||||
<AssemblyName>SmartThreadPoolMono</AssemblyName>
|
||||
<RootNamespace>Amib.Threading</RootNamespace>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>.\bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;NO_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>.\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NO_WINDOWS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CallerThreadContext.cs" />
|
||||
<Compile Include="CanceledWorkItemsGroup.cs" />
|
||||
<Compile Include="EventWaitHandleFactory.cs" />
|
||||
<Compile Include="Exceptions.cs" />
|
||||
<Compile Include="Interfaces.cs" />
|
||||
<Compile Include="InternalInterfaces.cs" />
|
||||
<Compile Include="PriorityQueue.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SmartThreadPool.cs" />
|
||||
<Compile Include="SmartThreadPool.ThreadEntry.cs" />
|
||||
<Compile Include="STPEventWaitHandle.cs" />
|
||||
<Compile Include="STPPerformanceCounter.cs" />
|
||||
<Compile Include="STPStartInfo.cs" />
|
||||
<Compile Include="SynchronizedDictionary.cs" />
|
||||
<Compile Include="WIGStartInfo.cs" />
|
||||
<Compile Include="WorkItem.cs" />
|
||||
<Compile Include="WorkItem.WorkItemResult.cs" />
|
||||
<Compile Include="WorkItemFactory.cs" />
|
||||
<Compile Include="WorkItemInfo.cs" />
|
||||
<Compile Include="WorkItemResultTWrapper.cs" />
|
||||
<Compile Include="WorkItemsGroup.cs" />
|
||||
<Compile Include="WorkItemsGroupBase.cs" />
|
||||
<Compile Include="WorkItemsQueue.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio AllowExistingFolder="true" />
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -0,0 +1,86 @@
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A6590A96-22B3-4889-B80E-2C398810E441}</ProjectGuid>
|
||||
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Amib.Threading</RootNamespace>
|
||||
<AssemblyName>SmartThreadPoolSL</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<SilverlightApplication>false</SilverlightApplication>
|
||||
<ValidateXaml>true</ValidateXaml>
|
||||
<ThrowErrorsInValidation>false</ThrowErrorsInValidation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>Bin\Debug</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;SILVERLIGHT,_WINDOWS</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>Bin\Release</OutputPath>
|
||||
<DefineConstants>TRACE;SILVERLIGHT,_WINDOWS</DefineConstants>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="system" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CallerThreadContext.cs" />
|
||||
<Compile Include="CanceledWorkItemsGroup.cs" />
|
||||
<Compile Include="EventWaitHandleFactory.cs" />
|
||||
<Compile Include="Exceptions.cs" />
|
||||
<Compile Include="Interfaces.cs" />
|
||||
<Compile Include="InternalInterfaces.cs" />
|
||||
<Compile Include="PriorityQueue.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SLExt.cs" />
|
||||
<Compile Include="SmartThreadPool.cs" />
|
||||
<Compile Include="SmartThreadPool.ThreadEntry.cs" />
|
||||
<Compile Include="Stopwatch.cs" />
|
||||
<Compile Include="STPEventWaitHandle.cs" />
|
||||
<Compile Include="STPPerformanceCounter.cs" />
|
||||
<Compile Include="STPStartInfo.cs" />
|
||||
<Compile Include="SynchronizedDictionary.cs" />
|
||||
<Compile Include="WIGStartInfo.cs" />
|
||||
<Compile Include="WorkItem.cs" />
|
||||
<Compile Include="WorkItem.WorkItemResult.cs" />
|
||||
<Compile Include="WorkItemFactory.cs" />
|
||||
<Compile Include="WorkItemInfo.cs" />
|
||||
<Compile Include="WorkItemResultTWrapper.cs" />
|
||||
<Compile Include="WorkItemsGroup.cs" />
|
||||
<Compile Include="WorkItemsGroupBase.cs" />
|
||||
<Compile Include="WorkItemsQueue.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
|
||||
<SilverlightProjectProperties />
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
|
||||
namespace Amib.Threading.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Stopwatch class
|
||||
/// Used with WindowsCE and Silverlight which don't have Stopwatch
|
||||
/// </summary>
|
||||
internal class Stopwatch
|
||||
{
|
||||
private long _elapsed;
|
||||
private bool _isRunning;
|
||||
private long _startTimeStamp;
|
||||
|
||||
public Stopwatch()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
private long GetElapsedDateTimeTicks()
|
||||
{
|
||||
long rawElapsedTicks = GetRawElapsedTicks();
|
||||
return rawElapsedTicks;
|
||||
}
|
||||
|
||||
private long GetRawElapsedTicks()
|
||||
{
|
||||
long elapsed = _elapsed;
|
||||
if (_isRunning)
|
||||
{
|
||||
long ticks = GetTimestamp() - _startTimeStamp;
|
||||
elapsed += ticks;
|
||||
}
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
public static long GetTimestamp()
|
||||
{
|
||||
return DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_elapsed = 0L;
|
||||
_isRunning = false;
|
||||
_startTimeStamp = 0L;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_startTimeStamp = GetTimestamp();
|
||||
_isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Stopwatch StartNew()
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
return stopwatch;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (_isRunning)
|
||||
{
|
||||
long ticks = GetTimestamp() - _startTimeStamp;
|
||||
_elapsed += ticks;
|
||||
_isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Properties
|
||||
public TimeSpan Elapsed
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TimeSpan(GetElapsedDateTimeTicks());
|
||||
}
|
||||
}
|
||||
|
||||
public long ElapsedMilliseconds
|
||||
{
|
||||
get
|
||||
{
|
||||
return (GetElapsedDateTimeTicks() / 0x2710L);
|
||||
}
|
||||
}
|
||||
|
||||
public long ElapsedTicks
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetRawElapsedTicks();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isRunning;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,97 +167,5 @@ namespace Amib.Threading
|
||||
{
|
||||
return new WIGStartInfo(this) { _readOnly = true };
|
||||
}
|
||||
/*
|
||||
#region WIGStartInfoRO class
|
||||
|
||||
/// <summary>
|
||||
/// A readonly version of WIGStartInfo
|
||||
/// </summary>
|
||||
private class WIGStartInfoRO : WIGStartInfo
|
||||
{
|
||||
private readonly WIGStartInfo _wigStartInfoRO;
|
||||
|
||||
public WIGStartInfoRO(WIGStartInfo wigStartInfoRO)
|
||||
{
|
||||
_wigStartInfoRO = wigStartInfoRO;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to use the caller's security context
|
||||
/// </summary>
|
||||
public override bool UseCallerCallContext
|
||||
{
|
||||
get { return _wigStartInfoRO.UseCallerCallContext; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to use the caller's HTTP context
|
||||
/// </summary>
|
||||
public override bool UseCallerHttpContext
|
||||
{
|
||||
get { return _wigStartInfoRO.UseCallerHttpContext; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if to dispose of the state object of a work item
|
||||
/// </summary>
|
||||
public override bool DisposeOfStateObjects
|
||||
{
|
||||
get { return _wigStartInfoRO.DisposeOfStateObjects; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the run the post execute options
|
||||
/// </summary>
|
||||
public override CallToPostExecute CallToPostExecute
|
||||
{
|
||||
get { return _wigStartInfoRO.CallToPostExecute; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default post execute callback
|
||||
/// </summary>
|
||||
public override PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||
{
|
||||
get { return _wigStartInfoRO.PostExecuteWorkItemCallback; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if the work items execution should be suspended until the Start()
|
||||
/// method is called.
|
||||
/// </summary>
|
||||
public override bool StartSuspended
|
||||
{
|
||||
get { return _wigStartInfoRO.StartSuspended; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the default priority that a work item gets when it is enqueued
|
||||
/// </summary>
|
||||
public override WorkItemPriority WorkItemPriority
|
||||
{
|
||||
get { return _wigStartInfoRO.WorkItemPriority; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if QueueWorkItem of Action<...>/Func<...> fill the
|
||||
/// arguments as an object array into the state of the work item.
|
||||
/// The arguments can be access later by IWorkItemResult.State.
|
||||
/// </summary>
|
||||
public override bool FillStateWithArgs
|
||||
{
|
||||
get { return _wigStartInfoRO.FillStateWithArgs; }
|
||||
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Amib.Threading.Internal
|
||||
/// <summary>
|
||||
/// Stores the caller's context
|
||||
/// </summary>
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
private readonly CallerThreadContext _callerContext;
|
||||
#endif
|
||||
/// <summary>
|
||||
@@ -138,23 +138,18 @@ namespace Amib.Threading.Internal
|
||||
|
||||
#region Performance Counter fields
|
||||
|
||||
/// <summary>
|
||||
/// The time when the work items is queued.
|
||||
/// Used with the performance counter.
|
||||
/// </summary>
|
||||
private DateTime _queuedTime;
|
||||
|
||||
/// <summary>
|
||||
/// The time when the work items starts its execution.
|
||||
/// Used with the performance counter.
|
||||
/// </summary>
|
||||
private DateTime _beginProcessTime;
|
||||
|
||||
/// <summary>
|
||||
/// The time when the work items ends its execution.
|
||||
/// Used with the performance counter.
|
||||
/// </summary>
|
||||
private DateTime _endProcessTime;
|
||||
|
||||
/// <summary>
|
||||
/// Stores how long the work item waited on the stp queue
|
||||
/// </summary>
|
||||
private Stopwatch _waitingOnQueueStopwatch;
|
||||
|
||||
/// <summary>
|
||||
/// Stores how much time it took the work item to execute after it went out of the queue
|
||||
/// </summary>
|
||||
private Stopwatch _processingStopwatch;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -166,7 +161,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_beginProcessTime - _queuedTime);
|
||||
return _waitingOnQueueStopwatch.Elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +169,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_endProcessTime - _beginProcessTime);
|
||||
return _processingStopwatch.Elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +204,7 @@ namespace Amib.Threading.Internal
|
||||
_workItemsGroup = workItemsGroup;
|
||||
_workItemInfo = workItemInfo;
|
||||
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
|
||||
{
|
||||
_callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
|
||||
@@ -230,6 +225,8 @@ namespace Amib.Threading.Internal
|
||||
|
||||
_workItemCompleted = null;
|
||||
_workItemCompletedRefCount = 0;
|
||||
_waitingOnQueueStopwatch = new Stopwatch();
|
||||
_processingStopwatch = new Stopwatch();
|
||||
}
|
||||
|
||||
internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
|
||||
@@ -263,7 +260,8 @@ namespace Amib.Threading.Internal
|
||||
/// </returns>
|
||||
public bool StartingWorkItem()
|
||||
{
|
||||
_beginProcessTime = DateTime.Now;
|
||||
_waitingOnQueueStopwatch.Stop();
|
||||
_processingStopwatch.Start();
|
||||
|
||||
lock(this)
|
||||
{
|
||||
@@ -318,7 +316,7 @@ namespace Amib.Threading.Internal
|
||||
PostExecute();
|
||||
}
|
||||
|
||||
_endProcessTime = DateTime.Now;
|
||||
_processingStopwatch.Stop();
|
||||
}
|
||||
|
||||
internal void FireWorkItemCompleted()
|
||||
@@ -353,7 +351,7 @@ namespace Amib.Threading.Internal
|
||||
private void ExecuteWorkItem()
|
||||
{
|
||||
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
CallerThreadContext ctc = null;
|
||||
if (null != _callerContext)
|
||||
{
|
||||
@@ -377,7 +375,7 @@ namespace Amib.Threading.Internal
|
||||
exception = e;
|
||||
}
|
||||
|
||||
// Remove the value of the execution thread, so it will not be possible to cancel the work item
|
||||
// Remove the value of the execution thread, so it will be impossible to cancel the work item,
|
||||
// since it is already completed.
|
||||
// Cancelling a work item that already completed may cause the abortion of the next work item!!!
|
||||
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
||||
@@ -394,15 +392,17 @@ namespace Amib.Threading.Internal
|
||||
catch (ThreadAbortException tae)
|
||||
{
|
||||
// Check if the work item was cancelled
|
||||
if ((string)tae.ExceptionState == "Cancel")
|
||||
// If we got a ThreadAbortException and the STP is not shutting down, it means the
|
||||
// work items was cancelled.
|
||||
if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown)
|
||||
{
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
Thread.ResetAbort();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
if (null != _callerContext)
|
||||
{
|
||||
CallerThreadContext.Apply(ctc);
|
||||
@@ -484,13 +484,13 @@ namespace Amib.Threading.Internal
|
||||
|
||||
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
|
||||
{
|
||||
success = EventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||
success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = true;
|
||||
int millisecondsLeft = millisecondsTimeout;
|
||||
DateTime start = DateTime.Now;
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
|
||||
WaitHandle [] whs;
|
||||
if (null != cancelWaitHandle)
|
||||
@@ -517,8 +517,8 @@ namespace Amib.Threading.Internal
|
||||
}
|
||||
|
||||
whs[0] = waitHandles[i];
|
||||
int result = EventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
|
||||
if ((result > 0) || (EventWaitHandle.WaitTimeout == result))
|
||||
int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
|
||||
if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result))
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
@@ -527,8 +527,7 @@ namespace Amib.Threading.Internal
|
||||
if(!waitInfinitely)
|
||||
{
|
||||
// Update the time left to wait
|
||||
TimeSpan ts = DateTime.Now - start;
|
||||
millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
|
||||
millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -570,14 +569,14 @@ namespace Amib.Threading.Internal
|
||||
GetWaitHandles(waitableResults, waitHandles);
|
||||
}
|
||||
|
||||
int result = EventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||
int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||
|
||||
// Treat cancel as timeout
|
||||
if (null != cancelWaitHandle)
|
||||
{
|
||||
if (result == waitableResults.Length)
|
||||
{
|
||||
result = EventWaitHandle.WaitTimeout;
|
||||
result = STPEventWaitHandle.WaitTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,7 +674,7 @@ namespace Amib.Threading.Internal
|
||||
|
||||
internal void WorkItemIsQueued()
|
||||
{
|
||||
_queuedTime = DateTime.Now;
|
||||
_waitingOnQueueStopwatch.Start();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -714,7 +713,7 @@ namespace Amib.Threading.Internal
|
||||
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
||||
if (null != executionThread)
|
||||
{
|
||||
executionThread.Abort("Cancel");
|
||||
executionThread.Abort(); // "Cancel"
|
||||
success = true;
|
||||
signalComplete = true;
|
||||
}
|
||||
@@ -795,7 +794,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
WaitHandle wh = GetWaitHandle();
|
||||
|
||||
bool timeout = !wh.WaitOne(millisecondsTimeout, exitContext);
|
||||
bool timeout = !STPEventWaitHandle.WaitOne(wh, millisecondsTimeout, exitContext);
|
||||
|
||||
ReleaseWaitHandle();
|
||||
|
||||
@@ -807,7 +806,7 @@ namespace Amib.Threading.Internal
|
||||
else
|
||||
{
|
||||
WaitHandle wh = GetWaitHandle();
|
||||
int result = EventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
|
||||
int result = STPEventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
|
||||
ReleaseWaitHandle();
|
||||
|
||||
switch(result)
|
||||
@@ -818,7 +817,7 @@ namespace Amib.Threading.Internal
|
||||
// work item (not the get result)
|
||||
break;
|
||||
case 1:
|
||||
case EventWaitHandle.WaitTimeout:
|
||||
case STPEventWaitHandle.WaitTimeout:
|
||||
throw new WorkItemTimeoutException("Work item timeout");
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"concurrency",
|
||||
#if !(WindowsCE)
|
||||
#if !(WindowsCE) && !(SILVERLIGHT)
|
||||
concurrency,
|
||||
#endif
|
||||
"concurrency must be greater than zero");
|
||||
@@ -166,7 +166,7 @@ namespace Amib.Threading.Internal
|
||||
}
|
||||
_isSuspended = false;
|
||||
|
||||
EnqueueToSTPNextNWorkItem(_concurrency);
|
||||
EnqueueToSTPNextNWorkItem(Math.Min(_workItemsQueue.Count, _concurrency));
|
||||
}
|
||||
|
||||
public override void Cancel(bool abortExecution)
|
||||
@@ -191,7 +191,7 @@ namespace Amib.Threading.Internal
|
||||
public override bool WaitForIdle(int millisecondsTimeout)
|
||||
{
|
||||
SmartThreadPool.ValidateWorkItemsGroupWaitForIdle(this);
|
||||
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
||||
return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false);
|
||||
}
|
||||
|
||||
public override event WorkItemsGroupIdleHandler OnIdle
|
||||
@@ -325,7 +325,7 @@ namespace Amib.Threading.Internal
|
||||
_stp.UnregisterWorkItemsGroup(this);
|
||||
IsIdle = true;
|
||||
_isIdleWaitHandle.Set();
|
||||
if (decrementWorkItemsInStpQueue)
|
||||
if (decrementWorkItemsInStpQueue && _onIdle.GetInvocationList().Length > 0)
|
||||
{
|
||||
_stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
|
||||
}
|
||||
|
||||
@@ -165,40 +165,49 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
// This method cause the caller to wait for a work item.
|
||||
// If there is at least one waiting work item then the
|
||||
// method returns immidiately with true.
|
||||
// method returns immidiately with it.
|
||||
//
|
||||
// If there are no waiting work items then the caller
|
||||
// is queued between other waiters for a work item to arrive.
|
||||
//
|
||||
// If a work item didn't come within millisecondsTimeout or
|
||||
// the user canceled the wait by signaling the cancelEvent
|
||||
// then the method returns false to indicate that the caller
|
||||
// then the method returns null to indicate that the caller
|
||||
// didn't get a work item.
|
||||
|
||||
WaiterEntry waiterEntry;
|
||||
WorkItem workItem = null;
|
||||
|
||||
lock(this)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!Monitor.TryEnter(this)) { }
|
||||
//Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
//Monitor.Enter(this);
|
||||
//stopwatch.Stop();
|
||||
|
||||
ValidateNotDisposed();
|
||||
|
||||
// If there are waiting work items then take one and return.
|
||||
if (_workItems.Count > 0)
|
||||
{
|
||||
workItem = _workItems.Dequeue() as WorkItem;
|
||||
return workItem;
|
||||
}
|
||||
// If there are waiting work items then take one and return.
|
||||
if (_workItems.Count > 0)
|
||||
{
|
||||
workItem = _workItems.Dequeue() as WorkItem;
|
||||
return workItem;
|
||||
}
|
||||
|
||||
// No waiting work items ...
|
||||
// No waiting work items ...
|
||||
|
||||
// Get the wait entry for the waiters queue
|
||||
waiterEntry = GetThreadWaiterEntry();
|
||||
// Get the waiter entry for the waiters queue
|
||||
waiterEntry = GetThreadWaiterEntry();
|
||||
|
||||
// Put the waiter with the other waiters
|
||||
PushWaiter(waiterEntry);
|
||||
}
|
||||
// Put the waiter with the other waiters
|
||||
PushWaiter(waiterEntry);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(this);
|
||||
}
|
||||
|
||||
// Prepare array of wait handle for the WaitHandle.WaitAny()
|
||||
// Prepare array of wait handle for the WaitHandle.WaitAny()
|
||||
WaitHandle [] waitHandles = new WaitHandle[] {
|
||||
waiterEntry.WaitHandle,
|
||||
cancelEvent };
|
||||
@@ -208,9 +217,9 @@ namespace Amib.Threading.Internal
|
||||
// During the wait we are supposes to exit the synchronization
|
||||
// domain. (Placing true as the third argument of the WaitAny())
|
||||
// It just doesn't work, I don't know why, so I have two lock(this)
|
||||
// statments insted of one.
|
||||
// statments instead of one.
|
||||
|
||||
int index = EventWaitHandle.WaitAny(
|
||||
int index = STPEventWaitHandle.WaitAny(
|
||||
waitHandles,
|
||||
millisecondsTimeout,
|
||||
true);
|
||||
@@ -506,10 +515,7 @@ namespace Amib.Threading.Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
return _workItem;
|
||||
}
|
||||
return _workItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,21 +47,78 @@ namespace TestSmartThreadPool
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.GroupBox groupBox4;
|
||||
private UsageControl.UsageHistoryControl usageHistorySTP;
|
||||
private System.Diagnostics.PerformanceCounter pcActiveThreads;
|
||||
private System.Diagnostics.PerformanceCounter pcInUseThreads;
|
||||
private System.Diagnostics.PerformanceCounter pcQueuedWorkItems;
|
||||
private System.Diagnostics.PerformanceCounter pcCompletedWorkItems;
|
||||
private long workItemsCompleted;
|
||||
|
||||
#if _WINDOWS
|
||||
|
||||
private System.Diagnostics.PerformanceCounter _pcActiveThreads;
|
||||
private System.Diagnostics.PerformanceCounter _pcInUseThreads;
|
||||
private System.Diagnostics.PerformanceCounter _pcQueuedWorkItems;
|
||||
private System.Diagnostics.PerformanceCounter _pcCompletedWorkItems;
|
||||
#endif
|
||||
|
||||
|
||||
private Func<long> _getActiveThreads;
|
||||
private Func<long> _getInUseThreads;
|
||||
private Func<long> _getQueuedWorkItems;
|
||||
private Func<long> _getCompletedWorkItems;
|
||||
|
||||
public Form1()
|
||||
{
|
||||
//
|
||||
// Required for Windows Form Designer support
|
||||
//
|
||||
InitializeComponent();
|
||||
|
||||
InitializeGUIPerformanceCounters();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
private void InitializeGUIPerformanceCounters()
|
||||
{
|
||||
#if _WINDOWS
|
||||
this._pcActiveThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcInUseThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcQueuedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcCompletedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
|
||||
//
|
||||
// pcActiveThreads
|
||||
//
|
||||
this._pcActiveThreads.CategoryName = "SmartThreadPool";
|
||||
this._pcActiveThreads.CounterName = "Active threads";
|
||||
this._pcActiveThreads.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcInUseThreads
|
||||
//
|
||||
this._pcInUseThreads.CategoryName = "SmartThreadPool";
|
||||
this._pcInUseThreads.CounterName = "In use threads";
|
||||
this._pcInUseThreads.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcQueuedWorkItems
|
||||
//
|
||||
this._pcQueuedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this._pcQueuedWorkItems.CounterName = "Work Items in queue";
|
||||
this._pcQueuedWorkItems.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcCompletedWorkItems
|
||||
//
|
||||
this._pcCompletedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this._pcCompletedWorkItems.CounterName = "Work Items processed";
|
||||
this._pcCompletedWorkItems.InstanceName = "Test SmartThreadPool";
|
||||
|
||||
_getActiveThreads = () => (long)_pcActiveThreads.NextValue();
|
||||
_getInUseThreads = () => (long)_pcInUseThreads.NextValue();
|
||||
_getQueuedWorkItems = () => (long)_pcQueuedWorkItems.NextValue();
|
||||
_getCompletedWorkItems = () => (long)_pcCompletedWorkItems.NextValue();
|
||||
#else
|
||||
_getActiveThreads = delegate () { return _smartThreadPool.PerformanceCountersReader.ActiveThreads; };
|
||||
_getInUseThreads = delegate () { return _smartThreadPool.PerformanceCountersReader.InUseThreads; };
|
||||
_getQueuedWorkItems = delegate () { return _smartThreadPool.PerformanceCountersReader.WorkItemsQueued; };
|
||||
_getCompletedWorkItems = delegate () { return _smartThreadPool.PerformanceCountersReader.WorkItemsProcessed; };
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
protected override void Dispose( bool disposing )
|
||||
@@ -114,10 +171,6 @@ namespace TestSmartThreadPool
|
||||
this.usageThreadsInPool = new UsageControl.UsageControl();
|
||||
this.groupBox4 = new System.Windows.Forms.GroupBox();
|
||||
this.usageHistorySTP = new UsageControl.UsageHistoryControl();
|
||||
this.pcActiveThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcInUseThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcQueuedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcCompletedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinIdleTimeout)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinMaxThreads)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinMinThreads)).BeginInit();
|
||||
@@ -127,10 +180,6 @@ namespace TestSmartThreadPool
|
||||
this.groupBox3.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.groupBox4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcActiveThreads)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcInUseThreads)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcQueuedWorkItems)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcCompletedWorkItems)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// btnStart
|
||||
@@ -187,7 +236,6 @@ namespace TestSmartThreadPool
|
||||
this.label4.TabIndex = 5;
|
||||
this.label4.Text = "Idle timeout (Seconds)";
|
||||
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.label4.Click += new System.EventHandler(this.label4_Click);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
@@ -245,6 +293,11 @@ namespace TestSmartThreadPool
|
||||
this.spinMaxThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.spinMaxThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.spinMaxThreads.Location = new System.Drawing.Point(8, 288);
|
||||
this.spinMaxThreads.Maximum = new decimal(new int[] {
|
||||
25,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.spinMaxThreads.Minimum = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
@@ -266,6 +319,11 @@ namespace TestSmartThreadPool
|
||||
this.spinMinThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.spinMinThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.spinMinThreads.Location = new System.Drawing.Point(8, 256);
|
||||
this.spinMinThreads.Maximum = new decimal(new int[] {
|
||||
25,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.spinMinThreads.Name = "spinMinThreads";
|
||||
this.spinMinThreads.Size = new System.Drawing.Size(88, 29);
|
||||
this.spinMinThreads.TabIndex = 13;
|
||||
@@ -494,35 +552,11 @@ namespace TestSmartThreadPool
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.usageHistorySTP.BackColor = System.Drawing.Color.Black;
|
||||
this.usageHistorySTP.Location = new System.Drawing.Point(8, 16);
|
||||
this.usageHistorySTP.Maximum = 100;
|
||||
this.usageHistorySTP.Maximum = 25;
|
||||
this.usageHistorySTP.Name = "usageHistorySTP";
|
||||
this.usageHistorySTP.Size = new System.Drawing.Size(480, 104);
|
||||
this.usageHistorySTP.TabIndex = 0;
|
||||
//
|
||||
// pcActiveThreads
|
||||
//
|
||||
this.pcActiveThreads.CategoryName = "SmartThreadPool";
|
||||
this.pcActiveThreads.CounterName = "Active threads";
|
||||
this.pcActiveThreads.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcInUseThreads
|
||||
//
|
||||
this.pcInUseThreads.CategoryName = "SmartThreadPool";
|
||||
this.pcInUseThreads.CounterName = "In use threads";
|
||||
this.pcInUseThreads.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcQueuedWorkItems
|
||||
//
|
||||
this.pcQueuedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this.pcQueuedWorkItems.CounterName = "Work Items in queue";
|
||||
this.pcQueuedWorkItems.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// pcCompletedWorkItems
|
||||
//
|
||||
this.pcCompletedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this.pcCompletedWorkItems.CounterName = "Work Items processed";
|
||||
this.pcCompletedWorkItems.InstanceName = "Test SmartThreadPool";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||
@@ -549,8 +583,8 @@ namespace TestSmartThreadPool
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Test Smart Thread Pool";
|
||||
this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.Closing += new System.ComponentModel.CancelEventHandler(this.Form1_Closing);
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinIdleTimeout)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinMaxThreads)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.spinMinThreads)).EndInit();
|
||||
@@ -560,10 +594,6 @@ namespace TestSmartThreadPool
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox4.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcActiveThreads)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcInUseThreads)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcQueuedWorkItems)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcCompletedWorkItems)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
@@ -575,11 +605,13 @@ namespace TestSmartThreadPool
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
#if _WINDOWS
|
||||
bool runApplication = InitializePerformanceCounters();
|
||||
if (!runApplication)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Application.EnableVisualStyles();
|
||||
|
||||
Application.Run(new Form1());
|
||||
@@ -652,6 +684,7 @@ namespace TestSmartThreadPool
|
||||
stpStartInfo.MaxWorkerThreads = Convert.ToInt32(spinMaxThreads.Value);
|
||||
stpStartInfo.MinWorkerThreads = Convert.ToInt32(spinMinThreads.Value);
|
||||
stpStartInfo.PerformanceCounterInstanceName = "Test SmartThreadPool";
|
||||
stpStartInfo.EnableLocalPerformanceCounters = true;
|
||||
|
||||
_smartThreadPool = new SmartThreadPool(stpStartInfo);
|
||||
|
||||
@@ -695,13 +728,13 @@ namespace TestSmartThreadPool
|
||||
lblThreadInUse.Text = "0";
|
||||
lblThreadsInPool.Text = "0";
|
||||
lblWaitingCallbacks.Text = "0";
|
||||
usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
||||
//usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
||||
usageThreadsInPool.Value1 = 0;
|
||||
usageThreadsInPool.Value2 = 0;
|
||||
lblWorkItemsCompleted.Text = "0";
|
||||
lblWorkItemsGenerated.Text = "0";
|
||||
usageHistorySTP.Reset();
|
||||
usageHistorySTP.Maximum = usageThreadsInPool.Maximum;
|
||||
//usageHistorySTP.Maximum = usageThreadsInPool.Maximum;
|
||||
}
|
||||
|
||||
private void spinMinThreads_ValueChanged(object sender, System.EventArgs e)
|
||||
@@ -723,7 +756,7 @@ namespace TestSmartThreadPool
|
||||
{
|
||||
spinMinThreads.Value = spinMaxThreads.Value;
|
||||
}
|
||||
usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
||||
//usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
||||
if (null != _smartThreadPool)
|
||||
{
|
||||
_smartThreadPool.MaxThreads = (int)spinMaxThreads.Value;
|
||||
@@ -738,15 +771,17 @@ namespace TestSmartThreadPool
|
||||
return;
|
||||
}
|
||||
|
||||
int threadsInUse = (int)pcInUseThreads.NextValue();
|
||||
int threadsInPool = (int)pcActiveThreads.NextValue();
|
||||
//int threadsInUse = (int)_pcInUseThreads.NextValue();
|
||||
//int threadsInPool = (int)_pcActiveThreads.NextValue();
|
||||
int threadsInUse = (int)_getInUseThreads();
|
||||
int threadsInPool = (int)_getActiveThreads();
|
||||
|
||||
lblThreadInUse.Text = threadsInUse.ToString();
|
||||
lblThreadsInPool.Text = threadsInPool.ToString();
|
||||
lblWaitingCallbacks.Text = pcQueuedWorkItems.NextValue().ToString(); //stp.WaitingCallbacks.ToString();
|
||||
lblWaitingCallbacks.Text = _getQueuedWorkItems().ToString(); //stp.WaitingCallbacks.ToString();
|
||||
usageThreadsInPool.Value1 = threadsInUse;
|
||||
usageThreadsInPool.Value2 = threadsInPool;
|
||||
lblWorkItemsCompleted.Text = pcCompletedWorkItems.NextValue().ToString();
|
||||
lblWorkItemsCompleted.Text = _getCompletedWorkItems().ToString();
|
||||
lblWorkItemsGenerated.Text = workItemsGenerated.ToString();
|
||||
usageHistorySTP.AddValues(threadsInUse, threadsInPool);
|
||||
}
|
||||
@@ -793,10 +828,5 @@ namespace TestSmartThreadPool
|
||||
_workItemsGroup = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void label4_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{976DB12F-9198-4AD9-981A-1652615C9B0D}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -33,7 +33,7 @@
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -56,7 +56,7 @@
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
@@ -72,16 +72,6 @@
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>
|
||||
</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{E8C4E483-0336-4D89-95F8-8924789ACA51}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>App.ico</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>TestSmartThreadPoolMono</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>TestSmartThreadPool</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>TestSmartThreadPool.Form1</StartupObject>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;DEBUG;NO_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>false</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||
<ConfigurationOverrideFile>
|
||||
</ConfigurationOverrideFile>
|
||||
<DefineConstants>TRACE;NO_WINDOWS</DefineConstants>
|
||||
<DocumentationFile>
|
||||
</DocumentationFile>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<NoStdLib>false</NoStdLib>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<Optimize>true</Optimize>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Data">
|
||||
<Name>System.Data</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing">
|
||||
<Name>System.Drawing</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Windows.Forms">
|
||||
<Name>System.Windows.Forms</Name>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml">
|
||||
<Name>System.XML</Name>
|
||||
</Reference>
|
||||
<ProjectReference Include="..\SmartThreadPool\SmartThreadPoolMono.csproj">
|
||||
<Project>{3462F30B-0156-409C-B256-6046D6F1764B}</Project>
|
||||
<Name>SmartThreadPoolMono</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\UsageControl\UsageControl.csproj">
|
||||
<Name>UsageControl</Name>
|
||||
<Project>{C11A4561-CCB5-4C96-8DF2-B804031D89D8}</Project>
|
||||
<Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App.ico" />
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{C11A4561-CCB5-4C96-8DF2-B804031D89D8}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -74,16 +74,6 @@
|
||||
<DebugType>none</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>
|
||||
</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
|
||||
@@ -91,10 +91,6 @@ namespace WorkItemsGroupDemo
|
||||
this.label19 = new System.Windows.Forms.Label();
|
||||
this.timer2 = new System.Windows.Forms.Timer(this.components);
|
||||
this.panelWIGsCtrls = new System.Windows.Forms.Panel();
|
||||
this.pcActiveThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcInUseThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcQueuedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
this.pcCompletedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
this.timerPoll = new System.Windows.Forms.Timer(this.components);
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.panel2 = new System.Windows.Forms.Panel();
|
||||
@@ -125,10 +121,6 @@ namespace WorkItemsGroupDemo
|
||||
this.groupWIGQueues.SuspendLayout();
|
||||
this.groupBox7.SuspendLayout();
|
||||
this.panelWIGsCtrls.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcActiveThreads)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcInUseThreads)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcQueuedWorkItems)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcCompletedWorkItems)).BeginInit();
|
||||
this.panel1.SuspendLayout();
|
||||
this.panel2.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
@@ -962,30 +954,6 @@ namespace WorkItemsGroupDemo
|
||||
this.panelWIGsCtrls.Size = new System.Drawing.Size(612, 105);
|
||||
this.panelWIGsCtrls.TabIndex = 1;
|
||||
//
|
||||
// pcActiveThreads
|
||||
//
|
||||
this.pcActiveThreads.CategoryName = "SmartThreadPool";
|
||||
this.pcActiveThreads.CounterName = "Active threads";
|
||||
this.pcActiveThreads.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcInUseThreads
|
||||
//
|
||||
this.pcInUseThreads.CategoryName = "SmartThreadPool";
|
||||
this.pcInUseThreads.CounterName = "In use threads";
|
||||
this.pcInUseThreads.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcQueuedWorkItems
|
||||
//
|
||||
this.pcQueuedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this.pcQueuedWorkItems.CounterName = "Work Items in queue";
|
||||
this.pcQueuedWorkItems.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcCompletedWorkItems
|
||||
//
|
||||
this.pcCompletedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this.pcCompletedWorkItems.CounterName = "Work Items processed";
|
||||
this.pcCompletedWorkItems.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// timerPoll
|
||||
//
|
||||
this.timerPoll.Interval = 500;
|
||||
@@ -1172,10 +1140,6 @@ namespace WorkItemsGroupDemo
|
||||
this.groupWIGQueues.ResumeLayout(false);
|
||||
this.groupBox7.ResumeLayout(false);
|
||||
this.panelWIGsCtrls.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcActiveThreads)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcInUseThreads)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcQueuedWorkItems)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pcCompletedWorkItems)).EndInit();
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel1.PerformLayout();
|
||||
this.panel2.ResumeLayout(false);
|
||||
@@ -1256,10 +1220,6 @@ namespace WorkItemsGroupDemo
|
||||
private System.Windows.Forms.Timer timer2;
|
||||
private System.Windows.Forms.Panel panelWIGsCtrls;
|
||||
private System.Windows.Forms.Button btnMode;
|
||||
private System.Diagnostics.PerformanceCounter pcActiveThreads;
|
||||
private System.Diagnostics.PerformanceCounter pcInUseThreads;
|
||||
private System.Diagnostics.PerformanceCounter pcQueuedWorkItems;
|
||||
private System.Diagnostics.PerformanceCounter pcCompletedWorkItems;
|
||||
private System.Windows.Forms.Timer timerPoll;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.Panel panel2;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using UsageControl;
|
||||
@@ -28,6 +29,19 @@ namespace WorkItemsGroupDemo
|
||||
private static readonly Color _wig2Color = Color.Green;
|
||||
private static readonly Color _wig3Color = Color.Blue;
|
||||
|
||||
#if _WINDOWS
|
||||
|
||||
private System.Diagnostics.PerformanceCounter _pcActiveThreads;
|
||||
private System.Diagnostics.PerformanceCounter _pcInUseThreads;
|
||||
private System.Diagnostics.PerformanceCounter _pcQueuedWorkItems;
|
||||
private System.Diagnostics.PerformanceCounter _pcCompletedWorkItems;
|
||||
#endif
|
||||
|
||||
|
||||
private Func<long> _getActiveThreads;
|
||||
private Func<long> _getInUseThreads;
|
||||
private Func<long> _getQueuedWorkItems;
|
||||
private Func<long> _getCompletedWorkItems;
|
||||
|
||||
private class WigEntry
|
||||
{
|
||||
@@ -53,6 +67,7 @@ namespace WorkItemsGroupDemo
|
||||
InitializeComponent();
|
||||
|
||||
InitSTP();
|
||||
InitializeGUIPerformanceCounters();
|
||||
|
||||
UpdateControls(false);
|
||||
UpdateModeControls();
|
||||
@@ -60,11 +75,15 @@ namespace WorkItemsGroupDemo
|
||||
|
||||
private void InitSTP()
|
||||
{
|
||||
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||
stpStartInfo.StartSuspended = true;
|
||||
stpStartInfo.MaxWorkerThreads = (int)spinCon6.Value;
|
||||
stpStartInfo.IdleTimeout = 5000;
|
||||
stpStartInfo.PerformanceCounterInstanceName = "SmartThreadPoolDemo";
|
||||
STPStartInfo stpStartInfo =
|
||||
new STPStartInfo
|
||||
{
|
||||
StartSuspended = true,
|
||||
MaxWorkerThreads = ((int)spinCon6.Value),
|
||||
IdleTimeout = int.Parse(spinIdleTimeout.Text)*1000,
|
||||
PerformanceCounterInstanceName = "SmartThreadPoolDemo",
|
||||
EnableLocalPerformanceCounters = true,
|
||||
};
|
||||
|
||||
_stp = new SmartThreadPool(stpStartInfo);
|
||||
_wig1 = _stp.CreateWorkItemsGroup((int)spinCon1.Value);
|
||||
@@ -93,6 +112,54 @@ namespace WorkItemsGroupDemo
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeGUIPerformanceCounters()
|
||||
{
|
||||
#if _WINDOWS
|
||||
this._pcActiveThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcInUseThreads = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcQueuedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
this._pcCompletedWorkItems = new System.Diagnostics.PerformanceCounter();
|
||||
|
||||
//
|
||||
// pcActiveThreads
|
||||
//
|
||||
this._pcActiveThreads.CategoryName = "SmartThreadPool";
|
||||
this._pcActiveThreads.CounterName = "Active threads";
|
||||
this._pcActiveThreads.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcInUseThreads
|
||||
//
|
||||
this._pcInUseThreads.CategoryName = "SmartThreadPool";
|
||||
this._pcInUseThreads.CounterName = "In use threads";
|
||||
this._pcInUseThreads.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcQueuedWorkItems
|
||||
//
|
||||
this._pcQueuedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this._pcQueuedWorkItems.CounterName = "Work Items in queue";
|
||||
this._pcQueuedWorkItems.InstanceName = "SmartThreadPoolDemo";
|
||||
//
|
||||
// pcCompletedWorkItems
|
||||
//
|
||||
this._pcCompletedWorkItems.CategoryName = "SmartThreadPool";
|
||||
this._pcCompletedWorkItems.CounterName = "Work Items processed";
|
||||
this._pcCompletedWorkItems.InstanceName = "SmartThreadPoolDemo";
|
||||
|
||||
_getActiveThreads = () => (long)_pcActiveThreads.NextValue();
|
||||
_getInUseThreads = () => (long)_pcInUseThreads.NextValue();
|
||||
_getQueuedWorkItems = () => (long)_pcQueuedWorkItems.NextValue();
|
||||
_getCompletedWorkItems = () => (long)_pcCompletedWorkItems.NextValue();
|
||||
#else
|
||||
_getActiveThreads = delegate () { return _stp.PerformanceCountersReader.ActiveThreads; };
|
||||
_getInUseThreads = delegate () { return _stp.PerformanceCountersReader.InUseThreads; };
|
||||
_getQueuedWorkItems = delegate () { return _stp.PerformanceCountersReader.WorkItemsQueued; };
|
||||
_getCompletedWorkItems = delegate () { return _stp.PerformanceCountersReader.WorkItemsProcessed; };
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void btnStart_Click(object sender, EventArgs e)
|
||||
{
|
||||
_running = !_running;
|
||||
@@ -152,6 +219,8 @@ namespace WorkItemsGroupDemo
|
||||
{
|
||||
break;
|
||||
}
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
//while (stopwatch.ElapsedMilliseconds < workItemState.SleepDuration);
|
||||
Thread.Sleep(workItemState.SleepDuration);
|
||||
} while (_paused);
|
||||
_workingStates.Remove(workItemState.QueueUsageEntry);
|
||||
@@ -177,7 +246,7 @@ namespace WorkItemsGroupDemo
|
||||
{
|
||||
lblStatus6.Text = _stp.IsIdle ? "Idle" : "Working";
|
||||
|
||||
object[] statesWorking;
|
||||
object [] statesWorking = null;
|
||||
lock (_workingStates.SyncRoot)
|
||||
{
|
||||
statesWorking = new object[_workingStates.Count];
|
||||
@@ -343,15 +412,15 @@ namespace WorkItemsGroupDemo
|
||||
return;
|
||||
}
|
||||
|
||||
int threadsInUse = (int)pcInUseThreads.NextValue();
|
||||
int threadsInPool = (int)pcActiveThreads.NextValue();
|
||||
int threadsInUse = (int)_getInUseThreads();
|
||||
int threadsInPool = (int)_getActiveThreads();
|
||||
|
||||
lblThreadInUse.Text = threadsInUse.ToString();
|
||||
lblThreadsInPool.Text = threadsInPool.ToString();
|
||||
lblWaitingCallbacks.Text = pcQueuedWorkItems.NextValue().ToString(); //stp.WaitingCallbacks.ToString();
|
||||
lblWaitingCallbacks.Text = _getQueuedWorkItems().ToString(); //stp.WaitingCallbacks.ToString();
|
||||
usageThreadsInPool.Value1 = threadsInUse;
|
||||
usageThreadsInPool.Value2 = threadsInPool;
|
||||
lblWorkItemsCompleted.Text = pcCompletedWorkItems.NextValue().ToString();
|
||||
lblWorkItemsCompleted.Text = _getCompletedWorkItems().ToString();
|
||||
lblWorkItemsGenerated.Text = _workItemsGenerated.ToString();
|
||||
usageHistorySTP.AddValues(threadsInUse, threadsInPool);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
@@ -21,7 +21,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;_WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
@@ -30,18 +30,10 @@
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;_WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
|
||||