using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading; 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; using System.Windows.Threading; using Amib.Threading; using Microsoft.Phone.Controls; namespace STPWPDemo { public partial class MainPage : PhoneApplicationPage { private const int MaxThreads = 10; private readonly DispatcherTimer _timer; private bool _running = false; private SmartThreadPool _stp; private readonly Thread _producer; private int _workItemPerSec; private int _workItemDuration; private readonly AutoResetEvent _wakeupEvent = new AutoResetEvent(false); // Constructork public MainPage() { InitializeComponent(); _timer = new DispatcherTimer(); _timer.Interval = new TimeSpan(0, 0, 0, 0, 500); _timer.Tick += _timer_Tick; _timer.Start(); _producer = new Thread(WorkItemsProducer); _producer.IsBackground = true; _workItemDuration = Convert.ToInt32(txtWorkItemDuration.Text); _workItemPerSec = Convert.ToInt32(txtWorkItemPerSec.Text); usageControl1.Visibility = Visibility.Visible; usageControl1.Maximum = MaxThreads; usageHistoryControl1.Maximum = MaxThreads; usageControl1.Maximum = Convert.ToInt32(txtMaxThreads.Text); usageControl1.Value1 = 0; usageControl1.Value2 = 0; _producer.Start(); } 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; txtUsedThreads.Text = threadsInUse.ToString(); txtThreadsInPool.Text = threadsInPool.ToString(); usageControl1.Value1 = threadsInUse; usageControl1.Value2 = threadsInPool; usageHistoryControl1.AddValues(threadsInUse, threadsInPool); } private void btnStart_Click(object sender, RoutedEventArgs e) { if (_running) { _wakeupEvent.Set(); _stp.Cancel(); _stp.Shutdown(false, 5000); _stp = null; btnStart.Content = "Start"; //txtIdleTimeout.Enabled = true; _running = false; } else { usageHistoryControl1.Reset(); usageControl1.Value1 = 0; usageControl1.Value2 = 0; _wakeupEvent.Set(); _running = true; btnStart.Content = "Stop"; //txtIdleTimeout.Enabled = false; STPStartInfo stpStartInfo = new STPStartInfo() { MinWorkerThreads = Convert.ToInt32(txtMinThreads.Text), MaxWorkerThreads = Convert.ToInt32(txtMaxThreads.Text), IdleTimeout = Convert.ToInt32(txtIdleTimeout.Text) * 1000, EnableLocalPerformanceCounters = true, }; _stp = new SmartThreadPool(stpStartInfo); } } private void WorkItemsProducer() { int timeout = _workItemPerSec == 0 ? Timeout.Infinite : (1000 / _workItemPerSec); while (true) { bool signal = _wakeupEvent.WaitOne(timeout); if (!signal) { SmartThreadPool stp = _stp; if (stp != null) { try { stp.QueueWorkItem(Sleep); } catch (Exception) { break; } } } else { // UI changed _workItemPerSec int workItemPerSec = _workItemPerSec; timeout = workItemPerSec == 0 ? Timeout.Infinite : (1000 / workItemPerSec); } } } private void Sleep() { Thread.Sleep(_workItemDuration); } private void spinMinThreads_Decrement(object sender, EventArgs eventArgs) { int minThreads = Step(txtMinThreads, 0, MaxThreads, -1); if (_stp != null) { _stp.MinThreads = minThreads; } } private void spinMinThreads_Increment(object sender, EventArgs eventArgs) { int minThreads = Step(txtMinThreads, 0, Convert.ToInt32(txtMaxThreads.Text), +1); if (_stp != null) { _stp.MinThreads = minThreads; } } private void spinMaxThreads_Decrement(object sender, EventArgs e) { int maxThreads = Step(txtMaxThreads, Convert.ToInt32(txtMinThreads.Text), 10, -1); if (_stp != null) { _stp.MaxThreads = maxThreads; } } private void spinMaxThreads_Increment(object sender, EventArgs e) { int maxThreads = Step(txtMaxThreads, 0, MaxThreads, +1); usageControl1.Maximum = maxThreads; usageHistoryControl1.Maximum = maxThreads; if (_stp != null) { _stp.MaxThreads = maxThreads; } } private void spinIdleTimeout_Decrement(object sender, EventArgs e) { Step(txtIdleTimeout, 0, 10, -1); } private void spinIdleTimeout_Increment(object sender, EventArgs e) { Step(txtIdleTimeout, 0, 10, +1); } private void spinWorkItemPerSec_Decrement(object sender, EventArgs e) { int workItemPerSec = _workItemPerSec; _workItemPerSec = Step(txtWorkItemPerSec, 0, 10, -1); if (workItemPerSec != _workItemPerSec) { _wakeupEvent.Set(); } } private void spinWorkItemPerSec_Increment(object sender, EventArgs e) { int workItemPerSec = _workItemPerSec; _workItemPerSec = Step(txtWorkItemPerSec, 0, 10, +1); if (workItemPerSec != _workItemPerSec) { _wakeupEvent.Set(); } } private void spinWorkItemDuration_Decrement(object sender, EventArgs e) { _workItemDuration = Step(txtWorkItemDuration, 0, 1000, -100); } private void spinWorkItemDuration_Increment(object sender, EventArgs e) { _workItemDuration = Step(txtWorkItemDuration, 0, 1000, +100); } private static int Step(TextBlock txtField, int minValue, int maxValue, int change) { int value = Convert.ToInt32(txtField.Text); value += change; if (value < minValue) { value = minValue; } if (value > maxValue) { value = maxValue; } txtField.Text = value.ToString(); return value; } } }