diff --git a/SmartThreadPool.sln b/SmartThreadPool.sln index 843908d..4fa3c54 100644 --- a/SmartThreadPool.sln +++ b/SmartThreadPool.sln @@ -35,6 +35,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B0 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C89D3C93-9BBC-47B9-943F-6962AACBE534}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkItemsGroupDemoMono", "WorkItemsGroupDemo\WorkItemsGroupDemoMono.csproj", "{4B1DED71-6B32-4D9A-A811-120E5F1187D9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -89,6 +91,10 @@ Global {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 + {4B1DED71-6B32-4D9A-A811-120E5F1187D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B1DED71-6B32-4D9A-A811-120E5F1187D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B1DED71-6B32-4D9A-A811-120E5F1187D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B1DED71-6B32-4D9A-A811-120E5F1187D9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -105,5 +111,6 @@ Global {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} + {4B1DED71-6B32-4D9A-A811-120E5F1187D9} = {9C6E9536-59A0-4F06-8085-0BB30ECB5158} EndGlobalSection EndGlobal diff --git a/TestSmartThreadPool/Form1.cs b/TestSmartThreadPool/Form1.cs index e251eea..d037ea3 100644 --- a/TestSmartThreadPool/Form1.cs +++ b/TestSmartThreadPool/Form1.cs @@ -10,7 +10,7 @@ namespace TestSmartThreadPool /// /// Summary description for Form1. /// - public class Form1 : System.Windows.Forms.Form + public partial class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button btnStart; private System.Windows.Forms.Button btnStop; @@ -63,6 +63,8 @@ namespace TestSmartThreadPool private Func _getQueuedWorkItems; private Func _getCompletedWorkItems; + private static bool _useWindowsPerformanceCounters; + public Form1() { // @@ -75,49 +77,66 @@ namespace TestSmartThreadPool 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 + if (_useWindowsPerformanceCounters) + { + InitializeWindowsPerformanceCounters(); + } + else + { + InitializeLocalPerformanceCounters(); + } } + partial void InitializeWindowsPerformanceCounters(); + +#if _WINDOWS + partial void InitializeWindowsPerformanceCounters() + { + 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(); + } +#endif + + private void InitializeLocalPerformanceCounters() + { + _getActiveThreads = () => _smartThreadPool.PerformanceCountersReader.ActiveThreads; + _getInUseThreads = () => _smartThreadPool.PerformanceCountersReader.InUseThreads; + _getQueuedWorkItems = () => _smartThreadPool.PerformanceCountersReader.WorkItemsQueued; + _getCompletedWorkItems = () => _smartThreadPool.PerformanceCountersReader.WorkItemsProcessed; + } + /// /// Clean up any resources being used. /// @@ -605,12 +624,10 @@ namespace TestSmartThreadPool [STAThread] static void Main() { -#if _WINDOWS - bool runApplication = InitializePerformanceCounters(); - if (!runApplication) - { - return; - } + //PerformanceCounterCategory.Delete("SmartThreadPool"); + //return; +#if _WINDOWS + _useWindowsPerformanceCounters = InitializePerformanceCounters(); #endif Application.EnableVisualStyles(); @@ -648,7 +665,7 @@ namespace TestSmartThreadPool if (!PerformanceCounterCategory.Exists("SmartThreadPool")) { - MessageBox.Show("Failed to create Performance Counters.", "Test Smart Thread Pool", MessageBoxButtons.OK, MessageBoxIcon.Error); + MessageBox.Show("Failed to create Performance Counters category.\r\nIf you run on Vista or Windows 7, you need to run for the first time as Administrator to create the performance counters category.\r\n\r\nUsing internal performance counters instead.", "Test Smart Thread Pool", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } @@ -683,8 +700,14 @@ namespace TestSmartThreadPool stpStartInfo.IdleTimeout = Convert.ToInt32(spinIdleTimeout.Value)*1000; stpStartInfo.MaxWorkerThreads = Convert.ToInt32(spinMaxThreads.Value); stpStartInfo.MinWorkerThreads = Convert.ToInt32(spinMinThreads.Value); - stpStartInfo.PerformanceCounterInstanceName = "Test SmartThreadPool"; - stpStartInfo.EnableLocalPerformanceCounters = true; + if (_useWindowsPerformanceCounters) + { + stpStartInfo.PerformanceCounterInstanceName = "Test SmartThreadPool"; + } + else + { + stpStartInfo.EnableLocalPerformanceCounters = true; + } _smartThreadPool = new SmartThreadPool(stpStartInfo); diff --git a/TestSmartThreadPool/TestSmartThreadPoolMono.csproj b/TestSmartThreadPool/TestSmartThreadPoolMono.csproj index 40c9cc3..45cae71 100644 --- a/TestSmartThreadPool/TestSmartThreadPoolMono.csproj +++ b/TestSmartThreadPool/TestSmartThreadPoolMono.csproj @@ -33,7 +33,7 @@ false - TRACE;DEBUG;NO_WINDOWS + TRACE;DEBUG;_MONO true @@ -56,7 +56,7 @@ false - TRACE;NO_WINDOWS + TRACE;_MONO false diff --git a/UsageControl/QueueUsageControl.cs b/UsageControl/QueueUsageControl.cs index 5c7b0fb..2b29cad 100644 --- a/UsageControl/QueueUsageControl.cs +++ b/UsageControl/QueueUsageControl.cs @@ -200,8 +200,17 @@ namespace UsageControl Bitmap bitmap = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(bitmap); + if (!Enabled) + { + g.FillPath(Brushes.LightGray, _pathBorder); + g.DrawPath(Pens.Black, _pathBorder); + e.Graphics.DrawImage(bitmap, 0, 0); + return; + } + g.FillPath(Brushes.White, _pathBorder); + int counter = Math.Min(_maxItemsVisible, _queuedItems.Count); int i = 0; diff --git a/WorkItemsGroupDemo/Form1.Designer.cs b/WorkItemsGroupDemo/Form1.Designer.cs index 172ad35..b81fa47 100644 --- a/WorkItemsGroupDemo/Form1.Designer.cs +++ b/WorkItemsGroupDemo/Form1.Designer.cs @@ -64,8 +64,14 @@ namespace WorkItemsGroupDemo this.comboWIPriority2 = new System.Windows.Forms.ComboBox(); this.comboWIPriority3 = new System.Windows.Forms.ComboBox(); this.btnMode = new System.Windows.Forms.Button(); + this.queueUsageControl6 = new UsageControl.QueueUsageControl(); + this.queueUsageControl2 = new UsageControl.QueueUsageControl(); + this.queueUsageControl1 = new UsageControl.QueueUsageControl(); + this.queueUsageControl3 = new UsageControl.QueueUsageControl(); + this.usageHistorySTP = new UsageControl.UsageHistoryControl(); this.groupBox4 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.usageThreadsInPool = new UsageControl.UsageControl(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.label6 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label(); @@ -95,12 +101,6 @@ namespace WorkItemsGroupDemo this.panel1 = new System.Windows.Forms.Panel(); this.panel2 = new System.Windows.Forms.Panel(); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.queueUsageControl6 = new UsageControl.QueueUsageControl(); - this.queueUsageControl2 = new UsageControl.QueueUsageControl(); - this.queueUsageControl1 = new UsageControl.QueueUsageControl(); - this.queueUsageControl3 = new UsageControl.QueueUsageControl(); - this.usageThreadsInPool = new UsageControl.UsageControl(); - this.usageHistorySTP = new UsageControl.UsageHistoryControl(); ((System.ComponentModel.ISupportInitialize)(this.spinCon6)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.spinCon1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.spinCon3)).BeginInit(); @@ -643,6 +643,78 @@ namespace WorkItemsGroupDemo this.btnMode.UseVisualStyleBackColor = true; this.btnMode.Click += new System.EventHandler(this.btnMode_Click); // + // queueUsageControl6 + // + this.queueUsageControl6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.queueUsageControl6.BackColor = System.Drawing.Color.Transparent; + this.queueUsageControl6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.queueUsageControl6.Location = new System.Drawing.Point(39, 19); + this.queueUsageControl6.Margin = new System.Windows.Forms.Padding(6); + this.queueUsageControl6.Name = "queueUsageControl6"; + this.queueUsageControl6.Size = new System.Drawing.Size(72, 346); + this.queueUsageControl6.TabIndex = 30; + this.queueUsageControl6.TabStop = false; + this.toolTip1.SetToolTip(this.queueUsageControl6, "Smart Thread Pool Queue. The head of the queue is at the bottom. Executed work i" + + "tems are shown blinking."); + // + // queueUsageControl2 + // + this.queueUsageControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.queueUsageControl2.BackColor = System.Drawing.Color.Transparent; + this.queueUsageControl2.CausesValidation = false; + this.queueUsageControl2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.queueUsageControl2.Location = new System.Drawing.Point(102, 44); + this.queueUsageControl2.Margin = new System.Windows.Forms.Padding(6); + this.queueUsageControl2.Name = "queueUsageControl2"; + this.queueUsageControl2.Size = new System.Drawing.Size(72, 321); + this.queueUsageControl2.TabIndex = 26; + this.toolTip1.SetToolTip(this.queueUsageControl2, "Work Items Group #2 Queue. Each Work Items Group has unique color for its work it" + + "ems."); + // + // queueUsageControl1 + // + this.queueUsageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.queueUsageControl1.BackColor = System.Drawing.Color.Transparent; + this.queueUsageControl1.CausesValidation = false; + this.queueUsageControl1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.queueUsageControl1.Location = new System.Drawing.Point(17, 44); + this.queueUsageControl1.Margin = new System.Windows.Forms.Padding(6); + this.queueUsageControl1.Name = "queueUsageControl1"; + this.queueUsageControl1.Size = new System.Drawing.Size(72, 321); + this.queueUsageControl1.TabIndex = 25; + this.toolTip1.SetToolTip(this.queueUsageControl1, "Work Items Group #1 Queue. Each Work Items Group has unique color for its work it" + + "ems."); + // + // queueUsageControl3 + // + this.queueUsageControl3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.queueUsageControl3.BackColor = System.Drawing.Color.Transparent; + this.queueUsageControl3.CausesValidation = false; + this.queueUsageControl3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.queueUsageControl3.Location = new System.Drawing.Point(186, 44); + this.queueUsageControl3.Margin = new System.Windows.Forms.Padding(6); + this.queueUsageControl3.Name = "queueUsageControl3"; + this.queueUsageControl3.Size = new System.Drawing.Size(72, 321); + this.queueUsageControl3.TabIndex = 27; + this.toolTip1.SetToolTip(this.queueUsageControl3, "Work Items Group #3 Queue. Each Work Items Group has unique color for its work it" + + "ems."); + // + // usageHistorySTP + // + this.usageHistorySTP.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | 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.Name = "usageHistorySTP"; + this.usageHistorySTP.Size = new System.Drawing.Size(501, 104); + this.usageHistorySTP.TabIndex = 0; + this.toolTip1.SetToolTip(this.usageHistorySTP, "Smart Thread Pool usage. Green means used threads. Red means threads in pool."); + // // groupBox4 // this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) @@ -665,6 +737,20 @@ namespace WorkItemsGroupDemo this.groupBox1.TabStop = false; this.groupBox1.Text = "STP Usage"; // + // usageThreadsInPool + // + this.usageThreadsInPool.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.usageThreadsInPool.BackColor = System.Drawing.Color.Black; + this.usageThreadsInPool.Location = new System.Drawing.Point(25, 16); + this.usageThreadsInPool.Maximum = 20; + this.usageThreadsInPool.Name = "usageThreadsInPool"; + this.usageThreadsInPool.Size = new System.Drawing.Size(41, 104); + this.usageThreadsInPool.TabIndex = 0; + this.usageThreadsInPool.Value1 = 0; + this.usageThreadsInPool.Value2 = 0; + // // groupBox2 // this.groupBox2.Controls.Add(this.lblWaitingCallbacks); @@ -755,6 +841,7 @@ namespace WorkItemsGroupDemo this.groupWIGQueues.Controls.Add(this.lblStatus2); this.groupWIGQueues.Controls.Add(this.lblStatus3); this.groupWIGQueues.Dock = System.Windows.Forms.DockStyle.Left; + this.groupWIGQueues.Enabled = false; this.groupWIGQueues.Location = new System.Drawing.Point(178, 3); this.groupWIGQueues.Name = "groupWIGQueues"; this.groupWIGQueues.Size = new System.Drawing.Size(275, 391); @@ -1020,92 +1107,6 @@ namespace WorkItemsGroupDemo this.tableLayoutPanel1.Size = new System.Drawing.Size(615, 557); this.tableLayoutPanel1.TabIndex = 95; // - // queueUsageControl6 - // - this.queueUsageControl6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); - this.queueUsageControl6.BackColor = System.Drawing.Color.Transparent; - this.queueUsageControl6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.queueUsageControl6.Location = new System.Drawing.Point(39, 19); - this.queueUsageControl6.Margin = new System.Windows.Forms.Padding(6); - this.queueUsageControl6.Name = "queueUsageControl6"; - this.queueUsageControl6.Size = new System.Drawing.Size(72, 346); - this.queueUsageControl6.TabIndex = 30; - this.queueUsageControl6.TabStop = false; - this.toolTip1.SetToolTip(this.queueUsageControl6, "Smart Thread Pool Queue. The head of the queue is at the bottom. Executed work i" + - "tems are shown blinking."); - // - // queueUsageControl2 - // - this.queueUsageControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.queueUsageControl2.BackColor = System.Drawing.Color.Transparent; - this.queueUsageControl2.CausesValidation = false; - this.queueUsageControl2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.queueUsageControl2.Location = new System.Drawing.Point(102, 44); - this.queueUsageControl2.Margin = new System.Windows.Forms.Padding(6); - this.queueUsageControl2.Name = "queueUsageControl2"; - this.queueUsageControl2.Size = new System.Drawing.Size(72, 321); - this.queueUsageControl2.TabIndex = 26; - this.toolTip1.SetToolTip(this.queueUsageControl2, "Work Items Group #2 Queue. Each Work Items Group has unique color for its work it" + - "ems."); - // - // queueUsageControl1 - // - this.queueUsageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.queueUsageControl1.BackColor = System.Drawing.Color.Transparent; - this.queueUsageControl1.CausesValidation = false; - this.queueUsageControl1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.queueUsageControl1.Location = new System.Drawing.Point(17, 44); - this.queueUsageControl1.Margin = new System.Windows.Forms.Padding(6); - this.queueUsageControl1.Name = "queueUsageControl1"; - this.queueUsageControl1.Size = new System.Drawing.Size(72, 321); - this.queueUsageControl1.TabIndex = 25; - this.toolTip1.SetToolTip(this.queueUsageControl1, "Work Items Group #1 Queue. Each Work Items Group has unique color for its work it" + - "ems."); - // - // queueUsageControl3 - // - this.queueUsageControl3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.queueUsageControl3.BackColor = System.Drawing.Color.Transparent; - this.queueUsageControl3.CausesValidation = false; - this.queueUsageControl3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.queueUsageControl3.Location = new System.Drawing.Point(186, 44); - this.queueUsageControl3.Margin = new System.Windows.Forms.Padding(6); - this.queueUsageControl3.Name = "queueUsageControl3"; - this.queueUsageControl3.Size = new System.Drawing.Size(72, 321); - this.queueUsageControl3.TabIndex = 27; - this.toolTip1.SetToolTip(this.queueUsageControl3, "Work Items Group #3 Queue. Each Work Items Group has unique color for its work it" + - "ems."); - // - // usageThreadsInPool - // - this.usageThreadsInPool.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.usageThreadsInPool.BackColor = System.Drawing.Color.Black; - this.usageThreadsInPool.Location = new System.Drawing.Point(25, 16); - this.usageThreadsInPool.Maximum = 20; - this.usageThreadsInPool.Name = "usageThreadsInPool"; - this.usageThreadsInPool.Size = new System.Drawing.Size(41, 104); - this.usageThreadsInPool.TabIndex = 0; - this.usageThreadsInPool.Value1 = 0; - this.usageThreadsInPool.Value2 = 0; - // - // usageHistorySTP - // - this.usageHistorySTP.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | 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.Name = "usageHistorySTP"; - this.usageHistorySTP.Size = new System.Drawing.Size(501, 104); - this.usageHistorySTP.TabIndex = 0; - this.toolTip1.SetToolTip(this.usageHistorySTP, "Smart Thread Pool usage. Green means used threads. Red means threads in pool."); - // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); diff --git a/WorkItemsGroupDemo/Form1.cs b/WorkItemsGroupDemo/Form1.cs index 4d96f8c..f298d49 100644 --- a/WorkItemsGroupDemo/Form1.cs +++ b/WorkItemsGroupDemo/Form1.cs @@ -17,7 +17,7 @@ namespace WorkItemsGroupDemo private bool _advancedMode = false; private int _workItemsGenerated; Hashtable _workingStates = Hashtable.Synchronized(new Hashtable()); - private SmartThreadPool _stp; + private SmartThreadPool _smartThreadPool; private IWorkItemsGroup _wig1; private IWorkItemsGroup _wig2; private IWorkItemsGroup _wig3; @@ -43,6 +43,8 @@ namespace WorkItemsGroupDemo private Func _getQueuedWorkItems; private Func _getCompletedWorkItems; + private static bool _useWindowsPerformanceCounters; + private class WigEntry { public IWorkItemsGroup _wig; @@ -80,20 +82,27 @@ namespace WorkItemsGroupDemo { StartSuspended = true, MaxWorkerThreads = ((int)spinCon6.Value), - IdleTimeout = int.Parse(spinIdleTimeout.Text)*1000, - PerformanceCounterInstanceName = "SmartThreadPoolDemo", - EnableLocalPerformanceCounters = true, + IdleTimeout = int.Parse(spinIdleTimeout.Text) * 1000, }; - _stp = new SmartThreadPool(stpStartInfo); - _wig1 = _stp.CreateWorkItemsGroup((int)spinCon1.Value); - _wig2 = _stp.CreateWorkItemsGroup((int)spinCon2.Value); - _wig3 = _stp.CreateWorkItemsGroup((int)spinCon3.Value); + if (_useWindowsPerformanceCounters) + { + stpStartInfo.PerformanceCounterInstanceName = "WIG Test SmartThreadPool"; + } + else + { + stpStartInfo.EnableLocalPerformanceCounters = true; + } + + _smartThreadPool = new SmartThreadPool(stpStartInfo); + _wig1 = _smartThreadPool.CreateWorkItemsGroup((int)spinCon1.Value); + _wig2 = _smartThreadPool.CreateWorkItemsGroup((int)spinCon2.Value); + _wig3 = _smartThreadPool.CreateWorkItemsGroup((int)spinCon3.Value); spinCon1.Tag = _wig1; spinCon2.Tag = _wig2; spinCon3.Tag = _wig3; - spinCon6.Tag = _stp; + spinCon6.Tag = _smartThreadPool; comboWIPriority1.SelectedIndex = 1; comboWIPriority2.SelectedIndex = 1; @@ -112,9 +121,85 @@ namespace WorkItemsGroupDemo } } - private void InitializeGUIPerformanceCounters() + public static void Init() { #if _WINDOWS + _useWindowsPerformanceCounters = InitializePerformanceCounters(); +#endif + } + + // This method is a work around for the Peformance Counter issue. + // When the first SmartThreadPool is created with a Peformance + // Counter name on a machine, it creates the SmartThreadPool + // Peformance Counter category. In this demo I am using the Performance + // Counters to update the GUI. + // The issue is that if this demo runs for the first time on the + // machine, it creates the Peformance Counter category and then + // uses it. + // I don't know why, but every time the demo runs for the first + // time on a machine, it fails to connect to the Peformance Counters, + // because it can't find the Peformance Counter category. + // The work around is to check if the category exists, and if not + // create a SmartThreadPool instance that will create the category. + // After that I spawn another process that runs the demo. + // I tried the another work around and thats to check for the category + // existance, run a second process that will create the category, + // and then continue with the first process, but it doesn't work. + // Thank you for reading the whole comment. If you have another way + // to solve this issue please contact me: amibar@gmail.com. + private static bool InitializePerformanceCounters() + { + if (!PerformanceCounterCategory.Exists("SmartThreadPool")) + { + STPStartInfo stpStartInfo = new STPStartInfo(); + stpStartInfo.PerformanceCounterInstanceName = "WIG Test SmartThreadPool"; + + SmartThreadPool stp = new SmartThreadPool(stpStartInfo); + stp.Shutdown(); + + if (!PerformanceCounterCategory.Exists("SmartThreadPool")) + { + MessageBox.Show("Failed to create Performance Counters category.\r\nIf you run on Vista or Windows 7, you need to run for the first time as Administrator to create the performance counters category.\r\n\r\nUsing internal performance counters instead.", "Test Smart Thread Pool", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + + Process process = new Process(); + process.StartInfo.FileName = Application.ExecutablePath; + + try + { + process.Start(); + } + catch (Exception e) + { + e.GetHashCode(); + MessageBox.Show("If this is the first time you get this message,\r\nplease try to run the demo again.", "Test Smart Thread Pool"); + } + + return false; + } + + return true; + } + + + private void InitializeGUIPerformanceCounters() + { + if (_useWindowsPerformanceCounters) + { + InitializeWindowsPerformanceCounters(); + } + else + { + InitializeLocalPerformanceCounters(); + } + } + + partial void InitializeWindowsPerformanceCounters(); + +#if _WINDOWS + partial void InitializeWindowsPerformanceCounters() + { this._pcActiveThreads = new System.Diagnostics.PerformanceCounter(); this._pcInUseThreads = new System.Diagnostics.PerformanceCounter(); this._pcQueuedWorkItems = new System.Diagnostics.PerformanceCounter(); @@ -125,40 +210,40 @@ namespace WorkItemsGroupDemo // this._pcActiveThreads.CategoryName = "SmartThreadPool"; this._pcActiveThreads.CounterName = "Active threads"; - this._pcActiveThreads.InstanceName = "SmartThreadPoolDemo"; + this._pcActiveThreads.InstanceName = "Test SmartThreadPool"; // // pcInUseThreads // this._pcInUseThreads.CategoryName = "SmartThreadPool"; this._pcInUseThreads.CounterName = "In use threads"; - this._pcInUseThreads.InstanceName = "SmartThreadPoolDemo"; + this._pcInUseThreads.InstanceName = "Test SmartThreadPool"; // // pcQueuedWorkItems // this._pcQueuedWorkItems.CategoryName = "SmartThreadPool"; this._pcQueuedWorkItems.CounterName = "Work Items in queue"; - this._pcQueuedWorkItems.InstanceName = "SmartThreadPoolDemo"; + this._pcQueuedWorkItems.InstanceName = "Test SmartThreadPool"; // // pcCompletedWorkItems // this._pcCompletedWorkItems.CategoryName = "SmartThreadPool"; this._pcCompletedWorkItems.CounterName = "Work Items processed"; - this._pcCompletedWorkItems.InstanceName = "SmartThreadPoolDemo"; + 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 _stp.PerformanceCountersReader.ActiveThreads; }; - _getInUseThreads = delegate () { return _stp.PerformanceCountersReader.InUseThreads; }; - _getQueuedWorkItems = delegate () { return _stp.PerformanceCountersReader.WorkItemsQueued; }; - _getCompletedWorkItems = delegate () { return _stp.PerformanceCountersReader.WorkItemsProcessed; }; - -#endif } +#endif - + private void InitializeLocalPerformanceCounters() + { + _getActiveThreads = () => _smartThreadPool.PerformanceCountersReader.ActiveThreads; + _getInUseThreads = () => _smartThreadPool.PerformanceCountersReader.InUseThreads; + _getQueuedWorkItems = () => _smartThreadPool.PerformanceCountersReader.WorkItemsQueued; + _getCompletedWorkItems = () => _smartThreadPool.PerformanceCountersReader.WorkItemsProcessed; + } private void btnStart_Click(object sender, EventArgs e) { @@ -179,7 +264,7 @@ namespace WorkItemsGroupDemo { _workItemsGenerated = 0; UpdateControls(true); - _stp.Start(); + _smartThreadPool.Start(); _wig1.Start(); _wig2.Start(); _wig3.Start(); @@ -187,7 +272,7 @@ namespace WorkItemsGroupDemo private void Shutdown() { - _stp.Shutdown(false, 2000); + _smartThreadPool.Shutdown(false, 2000); InitSTP(); UpdateControls(false); } @@ -244,7 +329,7 @@ namespace WorkItemsGroupDemo private void UpdateWorkingSet() { - lblStatus6.Text = _stp.IsIdle ? "Idle" : "Working"; + lblStatus6.Text = _smartThreadPool.IsIdle ? "Idle" : "Working"; object [] statesWorking = null; lock (_workingStates.SyncRoot) @@ -253,7 +338,7 @@ namespace WorkItemsGroupDemo _workingStates.Keys.CopyTo(statesWorking, 0); } - object[] statesSTP = _stp.GetStates(); + object[] statesSTP = _smartThreadPool.GetStates(); List list = new List(); @@ -373,7 +458,7 @@ namespace WorkItemsGroupDemo private void btnCancel6_Click(object sender, EventArgs e) { - _stp.Cancel(); + _smartThreadPool.Cancel(); } private void spinCon_ValueChanged(object sender, EventArgs e) @@ -388,7 +473,7 @@ namespace WorkItemsGroupDemo EnqueueWorkItems(ref _lastIndex[0], Convert.ToInt32(spinProduction1.Value), "#", _wig1Color, (WorkItemPriority)(2 * comboWIPriority1.SelectedIndex), _wig1, Convert.ToInt32(spinDuration1.Value)); EnqueueWorkItems(ref _lastIndex[1], Convert.ToInt32(spinProduction2.Value), "#", _wig2Color, (WorkItemPriority)(2 * comboWIPriority2.SelectedIndex), _wig2, Convert.ToInt32(spinDuration2.Value)); EnqueueWorkItems(ref _lastIndex[2], Convert.ToInt32(spinProduction3.Value), "#", _wig3Color, (WorkItemPriority)(2 * comboWIPriority3.SelectedIndex), _wig3, Convert.ToInt32(spinDuration3.Value)); - EnqueueWorkItems(ref _lastIndex[3], Convert.ToInt32(spinProduction6.Value), "#", _stpColor, (WorkItemPriority)(2 * comboWIPriority6.SelectedIndex), _stp, Convert.ToInt32(spinDuration6.Value)); + EnqueueWorkItems(ref _lastIndex[3], Convert.ToInt32(spinProduction6.Value), "#", _stpColor, (WorkItemPriority)(2 * comboWIPriority6.SelectedIndex), _smartThreadPool, Convert.ToInt32(spinDuration6.Value)); } private void btnMode_Click(object sender, EventArgs e) @@ -400,13 +485,13 @@ namespace WorkItemsGroupDemo private void UpdateModeControls() { btnMode.Text = _advancedMode ? "Basic <<" : "Advanced >>"; - panelWIGsCtrls.Visible = _advancedMode; - groupWIGQueues.Visible = _advancedMode; + panelWIGsCtrls.Enabled = _advancedMode; + groupWIGQueues.Enabled = _advancedMode; } private void timerPoll_Tick(object sender, EventArgs e) { - SmartThreadPool stp = _stp; + SmartThreadPool stp = _smartThreadPool; if (null == stp) { return; diff --git a/WorkItemsGroupDemo/Form1.resx b/WorkItemsGroupDemo/Form1.resx index d258e73..be70fdc 100644 --- a/WorkItemsGroupDemo/Form1.resx +++ b/WorkItemsGroupDemo/Form1.resx @@ -123,24 +123,9 @@ 17, 7 - - 94, 4 - 186, 4 - - 17, 54 - - - 150, 54 - - - 282, 54 - - - 438, 54 - 609, 54 diff --git a/WorkItemsGroupDemo/Program.cs b/WorkItemsGroupDemo/Program.cs index 779bdcf..05f56a2 100644 --- a/WorkItemsGroupDemo/Program.cs +++ b/WorkItemsGroupDemo/Program.cs @@ -11,6 +11,8 @@ namespace WorkItemsGroupDemo [STAThread] public static void Main() { + Form1.Init(); + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); diff --git a/WorkItemsGroupDemo/WorkItemsGroupDemoMono.csproj b/WorkItemsGroupDemo/WorkItemsGroupDemoMono.csproj new file mode 100644 index 0000000..bd9108f --- /dev/null +++ b/WorkItemsGroupDemo/WorkItemsGroupDemoMono.csproj @@ -0,0 +1,96 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {4B1DED71-6B32-4D9A-A811-120E5F1187D9} + WinExe + Properties + WorkItemsGroupDemo + WorkItemsGroupDemoMono + WorkItemsGroupDemo.Program + + + 2.0 + + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;_MONO + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE;_MONO + prompt + 4 + + + + + + + + + + + + Form + + + Form1.cs + + + + + Designer + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + {74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD} + SmartThreadPool + + + {C11A4561-CCB5-4C96-8DF2-B804031D89D8} + UsageControl + + + + + \ No newline at end of file