Added refactorings suggested by Simon Cropp

This commit is contained in:
Ami Bar
2009-12-19 17:33:30 +02:00
parent 1bd7e4d104
commit d2c14da5ad
62 changed files with 785 additions and 1131 deletions
+7 -12
View File
@@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Amib.Threading;
using System.Threading;
@@ -26,11 +21,11 @@ namespace STPCEDemo
uiTimer = new System.Windows.Forms.Timer();
uiTimer.Interval = 1000;
uiTimer.Tick += new EventHandler(uiTimer_Tick);
uiTimer.Tick += uiTimer_Tick;
wiTimer = new System.Windows.Forms.Timer();
wiTimer.Interval = 1000;
wiTimer.Tick += new EventHandler(wiTimer_Tick);
wiTimer.Tick += wiTimer_Tick;
//Debug.WriteLine("Form Thread Priority is " + (int)GetCurrentThreadPriority());
}
@@ -50,11 +45,11 @@ namespace STPCEDemo
int inUse = _stp.InUseThreads;
int inPool = _stp.ActiveThreads;
this.usageHistoryControl1.AddValues(inUse, inPool);
this.usageControl1.Value1 = inUse;
this.usageControl1.Value2 = inPool;
this.lblThreadsInUse.Text = inUse.ToString();
this.lblThreadsInPool.Text = inPool.ToString();
usageHistoryControl1.AddValues(inUse, inPool);
usageControl1.Value1 = inUse;
usageControl1.Value2 = inPool;
lblThreadsInUse.Text = inUse.ToString();
lblThreadsInPool.Text = inPool.ToString();
}
catch(Exception ex)
{
-3
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace STPCEDemo
{
-1
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace STPCEDemo
-1
View File
@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
+12 -16
View File
@@ -1,9 +1,5 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
using STPCEDemo;
@@ -12,7 +8,7 @@ namespace UsageControl
/// <summary>
/// Summary description for UsageControl.
/// </summary>
public class UsageControl : System.Windows.Forms.UserControl
public class UsageControl : UserControl
{
private System.ComponentModel.IContainer components = null;
@@ -83,7 +79,7 @@ namespace UsageControl
Width = fixedWidth;
rows = (ClientRectangle.Height / 4) - 1;
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
@@ -99,7 +95,7 @@ namespace UsageControl
int emptyCount = rows - Math.Max(filledCount1, filledCount2);
int i = 0;
int i;
for(i = 0; i < filledCount1; ++i)
{
@@ -176,7 +172,7 @@ namespace UsageControl
}
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
}
@@ -310,17 +306,17 @@ namespace UsageControl
int PenWidth = (int)Pens.White.Width;
g.DrawLine(Pens.DarkGray,
this.ClientRectangle.Left, this.ClientRectangle.Top,
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top);
ClientRectangle.Left, ClientRectangle.Top,
ClientRectangle.Width - PenWidth, ClientRectangle.Top);
g.DrawLine(Pens.DarkGray,
this.ClientRectangle.Left, this.ClientRectangle.Top,
this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth);
ClientRectangle.Left, ClientRectangle.Top,
ClientRectangle.Left, ClientRectangle.Height - PenWidth);
g.DrawLine(Pens.White,
this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth,
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth);
ClientRectangle.Left, ClientRectangle.Height - PenWidth,
ClientRectangle.Width - PenWidth, ClientRectangle.Height - PenWidth);
g.DrawLine(Pens.White,
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top,
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth);
ClientRectangle.Width - PenWidth, ClientRectangle.Top,
ClientRectangle.Width - PenWidth, ClientRectangle.Height - PenWidth);
}
+3 -6
View File
@@ -1,8 +1,5 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using STPCEDemo;
@@ -11,7 +8,7 @@ namespace UsageControl
/// <summary>
/// Summary description for UsageHistoryControl.
/// </summary>
public class UsageHistoryControl : System.Windows.Forms.UserControl
public class UsageHistoryControl : UserControl
{
/// <summary>
/// Required designer variable.
@@ -94,7 +91,7 @@ namespace UsageControl
protected override void OnResize(EventArgs e)
{
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
@@ -184,7 +181,7 @@ namespace UsageControl
max = value;
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
}
-44
View File
@@ -1,11 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// 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("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -14,45 +8,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// 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.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
+1 -1
View File
@@ -23,7 +23,7 @@ namespace Examples
smartThreadPool.QueueWorkItem(new
WorkItemCallback(this.DoDiv), divArgs);
Exception e = null;
Exception e;
object obj = wir.GetResult(out e);
// e contains the expetion that DoDiv threw
if(null == e)
+2 -1
View File
@@ -1,3 +1,4 @@
using System;
using System.Diagnostics;
using Amib.Threading;
@@ -11,7 +12,7 @@ namespace Examples
IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
wig.OnIdle += new WorkItemsGroupIdleHandler(wig_OnIdle);
wig.OnIdle += wig_OnIdle;
foreach(object state in states)
{
+1
View File
@@ -1,3 +1,4 @@
using System;
using System.Diagnostics;
using Amib.Threading;
+2 -4
View File
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Amib.Threading;
namespace STPExamples
@@ -26,8 +24,8 @@ namespace STPExamples
{
SmartThreadPool stp = new SmartThreadPool();
stp.OnThreadInitialization += new ThreadInitializationHandler(OnInitialization);
stp.OnThreadTermination += new ThreadTerminationHandler(OnTermination);
stp.OnThreadInitialization += OnInitialization;
stp.OnThreadTermination += OnTermination;
stp.QueueWorkItem(DoSomeWork);
}
+1
View File
@@ -1,3 +1,4 @@
using System;
using Amib.Threading;
namespace Examples
+1
View File
@@ -1,3 +1,4 @@
using System;
using System.Threading;
using Amib.Threading;
+1
View File
@@ -1,3 +1,4 @@
using System;
using Amib.Threading;
namespace Examples
-44
View File
@@ -1,11 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// 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("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -14,45 +8,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// 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.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
-3
View File
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using NUnit.Framework;
using Amib.Threading;
/*
* The code below generates permutations.
*
+6 -18
View File
@@ -1,5 +1,6 @@
using System;
using System.Threading;
using Amib.Threading.Internal;
using NUnit.Framework;
using Amib.Threading;
@@ -628,25 +629,12 @@ namespace SmartThreadPoolTests
Assert.IsTrue(success);
}
private static WorkItemInfo GetCurrentWorkItemInfo()
{
object threadEntry = typeof(SmartThreadPool).GetField("_threadEntry", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
object workitem = threadEntry.GetType().GetField("_currentWorkItem", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(threadEntry);
WorkItemInfo wii = (WorkItemInfo)workitem.GetType().GetField("_workItemInfo", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(workitem);
return wii;
}
private class WorkItemInfoComparer
{
private WorkItemInfo _neededWorkItemInfo;
private object _state;
private int _sleepTime = 0;
public int SleepTime
{
get { return _sleepTime; }
set { _sleepTime = value; }
}
public int SleepTime { get; set; }
public WorkItemInfoComparer(WorkItemInfo workItemInfo)
{
@@ -665,12 +653,12 @@ namespace SmartThreadPoolTests
bool equals = object.Equals(_state, state);
if (equals)
{
WorkItemInfo currentWorkItemInfo = GetCurrentWorkItemInfo();
WorkItemInfo currentWorkItemInfo = SmartThreadPool.CurrentThreadEntry.CurrentWorkItem.WorkItemInfo;
equals = CompareWorkItemInfo(currentWorkItemInfo, _neededWorkItemInfo);
}
if (_sleepTime > 0)
if (SleepTime > 0)
{
Thread.Sleep(_sleepTime);
Thread.Sleep(SleepTime);
}
return equals;
+10 -11
View File
@@ -1,4 +1,3 @@
using System;
using System.Threading;
using NUnit.Framework;
@@ -28,7 +27,7 @@ namespace SmartThreadPoolTests
stpStartInfo.StartSuspended = true;
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
IWorkItemResult wir = stp.QueueWorkItem(delegate(object state) { return null; });
IWorkItemResult wir = stp.QueueWorkItem(arg => null);
wir.Cancel();
@@ -59,7 +58,7 @@ namespace SmartThreadPoolTests
SmartThreadPool stp = new SmartThreadPool();
IWorkItemResult wir = stp.QueueWorkItem(
delegate(object state) { waitToStart.Set(); Thread.Sleep(100); return null; }
state => { waitToStart.Set(); Thread.Sleep(100); return null; }
);
waitToStart.WaitOne();
@@ -98,7 +97,7 @@ namespace SmartThreadPoolTests
SmartThreadPool stp = new SmartThreadPool();
IWorkItemResult wir = stp.QueueWorkItem(
delegate(object state) { waitToStart.Set() ; Thread.Sleep(100); ++counter; return null; }
state => { waitToStart.Set() ; Thread.Sleep(100); ++counter; return null; }
);
waitToStart.WaitOne();
@@ -137,7 +136,7 @@ namespace SmartThreadPoolTests
SmartThreadPool stp = new SmartThreadPool();
IWorkItemResult wir = stp.QueueWorkItem(
delegate(object state) {
state => {
waitToStart.Set();
Thread.Sleep(100);
cancelled = SmartThreadPool.IsWorkItemCanceled;
@@ -174,7 +173,7 @@ namespace SmartThreadPoolTests
stpStartInfo.StartSuspended = true;
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
IWorkItemResult wir = stp.QueueWorkItem(delegate(object state) { return null; });
IWorkItemResult wir = stp.QueueWorkItem(state => { return null; });
int counter = 0;
@@ -217,7 +216,7 @@ namespace SmartThreadPoolTests
{
SmartThreadPool stp = new SmartThreadPool();
IWorkItemResult wir = stp.QueueWorkItem(
delegate(object state) { return 1; }
state => 1
);
stp.WaitForIdle();
@@ -250,7 +249,7 @@ namespace SmartThreadPoolTests
for (int i = 0; i < 10; i++)
{
stp.QueueWorkItem(
delegate(object state) { Thread.Sleep(500); ++counter; return null; }
state => { Thread.Sleep(500); ++counter; return null; }
);
}
@@ -285,7 +284,7 @@ namespace SmartThreadPoolTests
for (int i = 0; i < 10; i++)
{
wig.QueueWorkItem(
delegate(object state) { Thread.Sleep(500); ++counter; return null; }
state => { Thread.Sleep(500); ++counter; return null; }
);
}
@@ -324,14 +323,14 @@ namespace SmartThreadPoolTests
for (int i = 0; i < 3; i++)
{
wig1.QueueWorkItem(
delegate(object state) { Interlocked.Increment(ref counter1); Thread.Sleep(500); Interlocked.Increment(ref counter1); return null; }
state => { Interlocked.Increment(ref counter1); Thread.Sleep(500); Interlocked.Increment(ref counter1); return null; }
);
}
for (int i = 0; i < 3; i++)
{
wig2.QueueWorkItem(
delegate(object state) { Thread.Sleep(500); Interlocked.Increment(ref counter2); return null; }
state => { Thread.Sleep(500); Interlocked.Increment(ref counter2); return null; }
);
}
+3 -11
View File
@@ -1,6 +1,4 @@
using System;
using System.Threading;
using NUnit.Framework;
using Amib.Threading;
@@ -14,11 +12,7 @@ namespace SmartThreadPoolTests
[Category("TestChainedDelegates")]
public class TestChainedDelegates
{
public TestChainedDelegates()
{
}
[Test]
[Test]
public void GoodCallback()
{
SmartThreadPool stp = new SmartThreadPool();
@@ -67,10 +61,8 @@ namespace SmartThreadPoolTests
{
SmartThreadPool stp = new SmartThreadPool();
PostExecuteWorkItemCallback postExecuteWorkItemCallback =
new PostExecuteWorkItemCallback(DoPostExecute);
postExecuteWorkItemCallback +=
new PostExecuteWorkItemCallback(DoPostExecute);
PostExecuteWorkItemCallback postExecuteWorkItemCallback = DoPostExecute;
postExecuteWorkItemCallback += DoPostExecute;
stp.QueueWorkItem(
new WorkItemCallback(DoWork),
+4 -10
View File
@@ -15,11 +15,7 @@ namespace SmartThreadPoolTests
[Category("TestConcurrencyChanges")]
public class TestConcurrencyChanges
{
public TestConcurrencyChanges()
{
}
/// <summary>
/// <summary>
/// Example of waiting for idle
/// </summary>
[Test]
@@ -27,8 +23,6 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool(1 * 1000, 1, 0);
bool success = false;
for (int i = 0; i < 100; ++i)
{
smartThreadPool.QueueWorkItem(
@@ -36,7 +30,7 @@ namespace SmartThreadPoolTests
null);
}
success = WaitForMaxThreadsValue(smartThreadPool, 1, 1 * 1000);
bool success = WaitForMaxThreadsValue(smartThreadPool, 1, 1 * 1000);
Assert.IsTrue(success);
smartThreadPool.MaxThreads = 5;
@@ -59,9 +53,9 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool(1 * 1000, 25, 0);
bool success = false;
success = WaitForMinThreadsValue(smartThreadPool, 0, 1 * 1000);
bool success = WaitForMinThreadsValue(smartThreadPool, 0, 1 * 1000);
Assert.IsTrue(success);
smartThreadPool.MinThreads = 5;
-3
View File
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Amib.Threading;
using NUnit.Framework;
+5 -10
View File
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Threading;
using NUnit.Framework;
@@ -111,9 +110,7 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool();
bool success = true;
IWorkItemResult [] wirs = new IWorkItemResult[5];
IWorkItemResult [] wirs = new IWorkItemResult[5];
for(int i = 0; i < wirs.Length; ++i)
{
@@ -122,7 +119,7 @@ namespace SmartThreadPoolTests
}
bool timeout = !SmartThreadPool.WaitAll(wirs, 1500, true);
success = !timeout;
bool success = !timeout;
smartThreadPool.Shutdown();
@@ -138,9 +135,7 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool();
bool success = true;
IWorkItemResult [] wirs = new IWorkItemResult[5];
IWorkItemResult [] wirs = new IWorkItemResult[5];
for(int i = 0; i < wirs.Length; ++i)
{
@@ -149,7 +144,7 @@ namespace SmartThreadPoolTests
}
bool timeout = !SmartThreadPool.WaitAll(wirs, 10, true);
success = timeout;
bool success = timeout;
smartThreadPool.Shutdown();
@@ -193,7 +188,7 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool();
bool success = true;
bool success;
IWorkItemResult [] wirs = new IWorkItemResult[5];
+6 -18
View File
@@ -15,11 +15,7 @@ namespace PriorityQueueTests
[Category("TestPriorityQueue")]
public class TestPriorityQueue
{
public TestPriorityQueue()
{
}
[Test]
[Test]
public void Init()
{
PriorityQueue pq = new PriorityQueue();
@@ -149,20 +145,12 @@ namespace PriorityQueueTests
private class PriorityItem : IHasWorkItemPriority
{
private WorkItemPriority _workItemPriority;
public PriorityItem(WorkItemPriority workItemPriority)
{
WorkItemPriority = workItemPriority;
}
public PriorityItem(WorkItemPriority workItemPriority)
{
_workItemPriority = workItemPriority;
}
public WorkItemPriority WorkItemPriority
{
get
{
return _workItemPriority;
}
}
public WorkItemPriority WorkItemPriority { get; private set; }
}
}
+1 -5
View File
@@ -14,11 +14,7 @@ namespace SmartThreadPoolTests
[Category("TestStartSuspended")]
public class TestStartSuspended
{
public TestStartSuspended()
{
}
[Test]
[Test]
public void StartSuspended()
{
STPStartInfo stpStartInfo = new STPStartInfo();
+4 -15
View File
@@ -9,16 +9,11 @@ namespace SmartThreadPoolTests
{
public class CallerState
{
private int _val = 0;
public int Value
{
get { return _val; }
}
public int Value { get; private set; }
protected void IncValue()
{
++_val;
++Value;
}
}
@@ -55,11 +50,7 @@ namespace SmartThreadPoolTests
[Category("TestStateDispose")]
public class TestStateDispose
{
public TestStateDispose()
{
}
/// <summary>
/// <summary>
/// Example of non disposable caller state
/// </summary>
[Test]
@@ -108,8 +99,6 @@ namespace SmartThreadPoolTests
SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
bool success = false;
CallerState nonDisposableCallerState = new NonDisposableCallerState();
CallerState disposableCallerState = new DisposableCallerState();
@@ -124,7 +113,7 @@ namespace SmartThreadPoolTests
disposableCallerState);
wir1.GetResult();
success = (1 == nonDisposableCallerState.Value);
bool success = (1 == nonDisposableCallerState.Value);
wir2.GetResult();
+3 -10
View File
@@ -1,5 +1,4 @@
using System;
using System.Threading;
using NUnit.Framework;
@@ -31,8 +30,8 @@ namespace SmartThreadPoolTests
SmartThreadPool stp = new SmartThreadPool();
stp.OnThreadInitialization += new ThreadInitializationHandler(OnInitialization);
stp.OnThreadTermination += new ThreadTerminationHandler(OnTermination);
stp.OnThreadInitialization += OnInitialization;
stp.OnThreadTermination += OnTermination;
stp.QueueWorkItem(new WorkItemCallback(DoSomeWork), null);
@@ -72,13 +71,7 @@ namespace SmartThreadPoolTests
[ThreadStatic]
private static ThreadContextState _threadContextState;
private int _counter = 0;
public int Counter
{
get { return _counter; }
set { _counter = value; }
}
public int Counter { get; set; }
// Static member so it can be used anywhere in code of the work item method
public static ThreadContextState Current
+1 -7
View File
@@ -1,6 +1,4 @@
using System;
using System.Threading;
using NUnit.Framework;
using Amib.Threading;
@@ -14,11 +12,7 @@ namespace WorkItemsGroupTests
[Category("Test WorkItemsGroup ChainedDelegates")]
public class TestChainedDelegates
{
public TestChainedDelegates()
{
}
[Test]
[Test]
public void GoodCallback()
{
SmartThreadPool smartThreadPool = new SmartThreadPool();
+1 -5
View File
@@ -19,11 +19,7 @@ namespace WorkItemsGroupTests
private int _concurrencyPerWig;
private bool _success;
public TestWIGConcurrency()
{
}
[Test]
[Test]
public void TestConcurrencies()
{
Concurrency(1, 1, 10);
+1 -7
View File
@@ -1,7 +1,5 @@
using System;
using System.Threading;
using System.Diagnostics;
using NUnit.Framework;
using Amib.Threading;
@@ -15,11 +13,7 @@ namespace WorkItemsGroupTests
[Category("TestWIGConcurrencyChanges")]
public class TestWIGConcurrencyChanges
{
public TestWIGConcurrencyChanges()
{
}
/// <summary>
/// <summary>
/// Example of waiting for idle
/// </summary>
[Test]
+1
View File
@@ -1,3 +1,4 @@
using System;
using Amib.Threading;
using NUnit.Framework;
+7 -14
View File
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Threading;
using NUnit.Framework;
@@ -114,9 +113,7 @@ namespace WorkItemsGroupTests
SmartThreadPool smartThreadPool = new SmartThreadPool();
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
bool success = true;
IWorkItemResult [] wirs = new IWorkItemResult[5];
IWorkItemResult [] wirs = new IWorkItemResult[5];
for(int i = 0; i < wirs.Length; ++i)
{
@@ -125,7 +122,7 @@ namespace WorkItemsGroupTests
}
bool timeout = !SmartThreadPool.WaitAll(wirs, 1500, true);
success = !timeout;
bool success = !timeout;
smartThreadPool.Shutdown();
@@ -142,9 +139,7 @@ namespace WorkItemsGroupTests
SmartThreadPool smartThreadPool = new SmartThreadPool();
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
bool success = true;
IWorkItemResult [] wirs = new IWorkItemResult[5];
IWorkItemResult [] wirs = new IWorkItemResult[5];
for(int i = 0; i < wirs.Length; ++i)
{
@@ -153,7 +148,7 @@ namespace WorkItemsGroupTests
}
bool timeout = !SmartThreadPool.WaitAll(wirs, 10, true);
success = timeout;
bool success = timeout;
smartThreadPool.Shutdown();
@@ -170,7 +165,7 @@ namespace WorkItemsGroupTests
SmartThreadPool smartThreadPool = new SmartThreadPool();
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
bool success = true;
bool success;
IWorkItemResult [] wirs = new IWorkItemResult[5];
@@ -199,9 +194,7 @@ namespace WorkItemsGroupTests
SmartThreadPool smartThreadPool = new SmartThreadPool();
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
bool success = true;
IWorkItemResult [] wirs = new IWorkItemResult[5];
IWorkItemResult [] wirs = new IWorkItemResult[5];
for(int i = 0; i < wirs.Length; ++i)
{
@@ -211,7 +204,7 @@ namespace WorkItemsGroupTests
int index = SmartThreadPool.WaitAny(wirs, 10, true);
success = (index == WaitHandle.WaitTimeout);
bool success = (index == WaitHandle.WaitTimeout);
smartThreadPool.Shutdown();
-3
View File
@@ -1,6 +1,3 @@
using System;
using System.Threading;
using NUnit.Framework;
using Amib.Threading;
+4 -15
View File
@@ -9,16 +9,11 @@ namespace WorkItemsGroupTests
{
public class CallerState
{
private int _val = 0;
public int Value
{
get { return _val; }
}
public int Value { get; private set; }
protected void IncValue()
{
++_val;
++Value;
}
}
@@ -55,11 +50,7 @@ namespace WorkItemsGroupTests
[Category("WorkItemsGroup")]
public class TestStateDispose
{
public TestStateDispose()
{
}
/// <summary>
/// <summary>
/// Example of non disposable caller state
/// </summary>
[Test]
@@ -112,8 +103,6 @@ namespace WorkItemsGroupTests
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue, wigStartInfo);
bool success = false;
CallerState nonDisposableCallerState = new NonDisposableCallerState();
CallerState disposableCallerState = new DisposableCallerState();
@@ -128,7 +117,7 @@ namespace WorkItemsGroupTests
disposableCallerState);
wir1.GetResult();
success = (1 == nonDisposableCallerState.Value);
bool success = (1 == nonDisposableCallerState.Value);
wir2.GetResult();
+2 -9
View File
@@ -1,7 +1,5 @@
using System;
using System.Threading;
using System.Diagnostics;
using NUnit.Framework;
using Amib.Threading;
@@ -15,11 +13,7 @@ namespace WorkItemsGroupTests
[Category("WorkItemsGroup")]
public class TestWaitForIdle
{
public TestWaitForIdle()
{
}
/// <summary>
/// <summary>
/// Example of waiting for idle
/// </summary>
[Test]
@@ -28,7 +22,6 @@ namespace WorkItemsGroupTests
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
bool success = false;
ManualResetEvent isRunning = new ManualResetEvent(false);
for (int i = 0; i < 4; ++i)
@@ -36,7 +29,7 @@ namespace WorkItemsGroupTests
workItemsGroup.QueueWorkItem(delegate { isRunning.WaitOne(); });
}
success = !workItemsGroup.WaitForIdle(1000);
bool success = !workItemsGroup.WaitForIdle(1000);
isRunning.Set();
+2 -7
View File
@@ -15,11 +15,7 @@ namespace SmartThreadPoolTests
[Category("TestWaitForIdle")]
public class TestWaitForIdle
{
public TestWaitForIdle()
{
}
/// <summary>
/// <summary>
/// Example of waiting for idle
/// </summary>
[Test]
@@ -27,7 +23,6 @@ namespace SmartThreadPoolTests
{
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
bool success = false;
ManualResetEvent isRunning = new ManualResetEvent(false);
for(int i = 0; i < 4; ++i)
@@ -35,7 +30,7 @@ namespace SmartThreadPoolTests
smartThreadPool.QueueWorkItem(delegate { isRunning.WaitOne(); });
}
success = !smartThreadPool.WaitForIdle(1000);
bool success = !smartThreadPool.WaitForIdle(1000);
isRunning.Set();
+1 -7
View File
@@ -1,7 +1,5 @@
using System;
using System.Threading;
using System.Diagnostics;
using NUnit.Framework;
using Amib.Threading;
@@ -15,11 +13,7 @@ namespace WorkItemsGroupTests
[Category("TestWorkItemsGroups")]
public class TestWorkItemsGroups
{
public TestWorkItemsGroups()
{
}
[Test]
[Test]
public void BlockingCall()
{
SmartThreadPool smartThreadPool = new SmartThreadPool();
+3 -13
View File
@@ -1,12 +1,6 @@
using System;
using NUnit.Framework;
using Amib.Threading;
using Amib.Threading.Internal;
using SmartThreadPoolTests;
namespace PriorityQueueTests
{
/// <summary>
@@ -16,11 +10,7 @@ namespace PriorityQueueTests
[Category("TestWorkItemsQueue")]
public class TestWorkItemsQueue
{
public TestWorkItemsQueue()
{
}
[Test]
[Test]
public void Init()
{
}
@@ -32,7 +22,7 @@ namespace PriorityQueueTests
Assert.AreEqual(0, q.WaitersCount);
WorkItemsQueue.WaiterEntry we1 = new Amib.Threading.Internal.WorkItemsQueue.WaiterEntry();
WorkItemsQueue.WaiterEntry we1 = new WorkItemsQueue.WaiterEntry();
q.PushWaiter(we1);
Assert.AreEqual(1, q.WaitersCount);
@@ -41,7 +31,7 @@ namespace PriorityQueueTests
Assert.AreEqual(1, q.WaitersCount);
WorkItemsQueue.WaiterEntry we2 = new Amib.Threading.Internal.WorkItemsQueue.WaiterEntry();
WorkItemsQueue.WaiterEntry we2 = new WorkItemsQueue.WaiterEntry();
q.PushWaiter(we2);
Assert.AreEqual(2, q.WaitersCount);
+2
View File
@@ -25,6 +25,7 @@ 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
@@ -53,6 +54,7 @@ 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
+14
View File
@@ -0,0 +1,14 @@
namespace Amib.Threading.Internal
{
internal class CanceledWorkItemsGroup
{
public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
public CanceledWorkItemsGroup()
{
IsCanceled = false;
}
public bool IsCanceled { get; set; }
}
}
+5 -5
View File
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Diagnostics;
#if (WindowsCE)
using System;
using System.Runtime.InteropServices;
#endif
namespace Amib.Threading.Internal
{
+3 -3
View File
@@ -10,7 +10,7 @@ namespace Amib.Threading
/// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
/// </summary>
public sealed partial class WorkItemCancelException : ApplicationException
public sealed partial class WorkItemCancelException : Exception
{
public WorkItemCancelException()
{
@@ -30,7 +30,7 @@ namespace Amib.Threading
/// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
/// </summary>
public sealed partial class WorkItemTimeoutException : ApplicationException
public sealed partial class WorkItemTimeoutException : Exception
{
public WorkItemTimeoutException()
{
@@ -50,7 +50,7 @@ namespace Amib.Threading
/// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
/// </summary>
public sealed partial class WorkItemResultException : ApplicationException
public sealed partial class WorkItemResultException : Exception
{
public WorkItemResultException()
{
+27
View File
@@ -0,0 +1,27 @@
namespace Amib.Threading.Internal
{
/// <summary>
/// An internal delegate to call when the WorkItem starts or completes
/// </summary>
internal delegate void WorkItemStateCallback(WorkItem workItem);
internal interface IInternalWorkItemResult
{
event WorkItemStateCallback OnWorkItemStarted;
event WorkItemStateCallback OnWorkItemCompleted;
}
internal interface IInternalWaitableResult
{
/// <summary>
/// This method is intent for internal use.
/// </summary>
IWorkItemResult GetWorkItemResult();
}
public interface IHasWorkItemPriority
{
WorkItemPriority WorkItemPriority { get; }
}
}
+2 -19
View File
@@ -2,9 +2,6 @@
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("Amib.Threading")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -13,23 +10,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("")]
[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("c764a3de-c4f8-434d-85b5-a09830d1e44f")]
[assembly: AssemblyVersion("2.0.1.0")]
[assembly: InternalsVisibleTo("STPTests")]
// 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("2.0.0.0")]
+3
View File
@@ -1,5 +1,8 @@
using System;
#if !(WindowsCE)
using System.Diagnostics;
#endif
namespace Amib.Threading.Internal
{
+88 -58
View File
@@ -8,83 +8,112 @@ namespace Amib.Threading
/// </summary>
public class STPStartInfo : WIGStartInfo
{
private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
private int _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority;
private string _pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
private int _idleTimeout;
private int _minWorkerThreads;
private int _maxWorkerThreads;
private ThreadPriority _threadPriority;
private string _performanceCounterInstanceName;
public STPStartInfo()
public STPStartInfo()
{
_performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
_threadPriority = SmartThreadPool.DefaultThreadPriority;
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
_idleTimeout = SmartThreadPool.DefaultIdleTimeout;
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
}
public STPStartInfo(STPStartInfo stpStartInfo)
public STPStartInfo(STPStartInfo stpStartInfo)
: base(stpStartInfo)
{
_idleTimeout = stpStartInfo._idleTimeout;
_minWorkerThreads = stpStartInfo._minWorkerThreads;
_maxWorkerThreads = stpStartInfo._maxWorkerThreads;
_threadPriority = stpStartInfo._threadPriority;
_pcInstanceName = stpStartInfo._pcInstanceName;
_idleTimeout = stpStartInfo.IdleTimeout;
_minWorkerThreads = stpStartInfo.MinWorkerThreads;
_maxWorkerThreads = stpStartInfo.MaxWorkerThreads;
_threadPriority = stpStartInfo.ThreadPriority;
_performanceCounterInstanceName = stpStartInfo.PerformanceCounterInstanceName;
}
/// <summary>
/// Get/Set the idle timeout in milliseconds.
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
/// </summary>
public virtual int IdleTimeout
{
get { return _idleTimeout; }
set { _idleTimeout = value; }
}
/// <summary>
/// Get/Set the idle timeout in milliseconds.
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
/// </summary>
public virtual int IdleTimeout
{
get { return _idleTimeout; }
set
{
ThrowIfReadOnly();
_idleTimeout = value;
}
}
/// <summary>
/// Get/Set the lower limit of threads in the pool.
/// </summary>
public virtual int MinWorkerThreads
{
get { return _minWorkerThreads; }
set { _minWorkerThreads = value; }
}
/// <summary>
/// Get/Set the upper limit of threads in the pool.
/// </summary>
public virtual int MaxWorkerThreads
{
get { return _maxWorkerThreads; }
set { _maxWorkerThreads = value; }
}
/// <summary>
/// Get/Set the lower limit of threads in the pool.
/// </summary>
public virtual int MinWorkerThreads
{
get { return _minWorkerThreads; }
set
{
ThrowIfReadOnly();
_minWorkerThreads = value;
}
}
/// <summary>
/// Get/Set the scheduling priority of the threads in the pool.
/// The Os handles the scheduling.
/// </summary>
public virtual ThreadPriority ThreadPriority
{
get { return _threadPriority; }
set { _threadPriority = value; }
}
/// <summary>
/// Get/Set the performance counter instance name of this SmartThreadPool
/// The default is null which indicate not to use performance counters at all.
/// </summary>
public virtual string PerformanceCounterInstanceName
{
get { return _pcInstanceName; }
set { _pcInstanceName = value; }
}
/// <summary>
/// Get/Set the upper limit of threads in the pool.
/// </summary>
public virtual int MaxWorkerThreads
{
get { return _maxWorkerThreads; }
set
{
ThrowIfReadOnly();
_maxWorkerThreads = value;
}
}
/// <summary>
/// <summary>
/// Get/Set the scheduling priority of the threads in the pool.
/// The Os handles the scheduling.
/// </summary>
public virtual ThreadPriority ThreadPriority
{
get { return _threadPriority; }
set
{
ThrowIfReadOnly();
_threadPriority = value;
}
}
/// <summary>
/// Get/Set the performance counter instance name of this SmartThreadPool
/// The default is null which indicate not to use performance counters at all.
/// </summary>
public virtual string PerformanceCounterInstanceName
{
get { return _performanceCounterInstanceName; }
set
{
ThrowIfReadOnly();
_performanceCounterInstanceName = value;
}
}
/// <summary>
/// Get a readonly version of this STPStartInfo.
/// </summary>
/// <returns>Returns a readonly reference to this STPStartInfo</returns>
public new STPStartInfo AsReadOnly()
{
return new STPStartInfoRO(this);
return new STPStartInfo(this) { _readOnly = true };
}
/*
#region STPStartInfoRO class
private class STPStartInfoRO : STPStartInfo
@@ -221,5 +250,6 @@ namespace Amib.Threading
}
#endregion
*/
}
}
@@ -0,0 +1,60 @@
using System;
using Amib.Threading.Internal;
namespace Amib.Threading
{
public partial class SmartThreadPool
{
#region ThreadEntry class
internal class ThreadEntry
{
/// <summary>
/// The thread creation time
/// The value is stored as UTC value.
/// </summary>
private readonly DateTime _creationTime;
/// <summary>
/// The last time this thread has been running
/// It is updated by IAmAlive() method
/// The value is stored as UTC value.
/// </summary>
private DateTime _lastAliveTime;
/// <summary>
/// A reference from each thread in the thread pool to its SmartThreadPool
/// object container.
/// With this variable a thread can know whatever it belongs to a
/// SmartThreadPool.
/// </summary>
private readonly SmartThreadPool _associatedSmartThreadPool;
/// <summary>
/// A reference to the current work item a thread from the thread pool
/// is executing.
/// </summary>
public WorkItem CurrentWorkItem { get; set; }
public ThreadEntry(SmartThreadPool stp)
{
_associatedSmartThreadPool = stp;
_creationTime = DateTime.UtcNow;
_lastAliveTime = DateTime.MinValue;
}
public SmartThreadPool AssociatedSmartThreadPool
{
get { return _associatedSmartThreadPool; }
}
public void IAmAlive()
{
_lastAliveTime = DateTime.UtcNow;
}
}
#endregion
}
}
+43 -94
View File
@@ -82,7 +82,7 @@ namespace Amib.Threading
/// <summary>
/// Smart thread pool class.
/// </summary>
public class SmartThreadPool : WorkItemsGroupBase, IDisposable
public partial class SmartThreadPool : WorkItemsGroupBase, IDisposable
{
#region Public Default Constants
@@ -156,61 +156,6 @@ namespace Amib.Threading
#endregion
#region ThreadEntry class
private class ThreadEntry
{
/// <summary>
/// The thread creation time
/// </summary>
private DateTime _creationTime;
/// <summary>
/// The last time this thread has been running
/// It is updated by IAmAlive() method
/// </summary>
private DateTime _lastAliveTime;
/// <summary>
/// A reference to the current work item a thread from the thread pool
/// is executing.
/// </summary>
private WorkItem _currentWorkItem;
/// <summary>
/// A reference from each thread in the thread pool to its SmartThreadPool
/// object container.
/// With this variable a thread can know whatever it belongs to a
/// SmartThreadPool.
/// </summary>
private SmartThreadPool _associatedSmartThreadPool;
public ThreadEntry(SmartThreadPool stp)
{
_associatedSmartThreadPool = stp;
_creationTime = DateTime.Now;
_lastAliveTime = DateTime.MinValue;
}
public WorkItem CurrentWorkItem
{
get { return _currentWorkItem; }
set { _currentWorkItem = value; }
}
public SmartThreadPool AssociatedSmartThreadPool
{
get { return _associatedSmartThreadPool; }
}
public void IAmAlive()
{
_lastAliveTime = DateTime.Now;
}
}
#endregion
#region Member Variables
/// <summary>
@@ -234,17 +179,11 @@ namespace Amib.Threading
/// </summary>
private int _inUseWorkerThreads;
/// <summary>
/// Start information to use.
/// It is simpler than providing many constructors.
/// </summary>
private STPStartInfo _stpStartInfo = new STPStartInfo();
/// <summary>
/// Stored the original reference to the provided _stpStartInfo.
/// Stores a copy of the original STPStartInfo.
/// It is used to change the MinThread and MaxThreads
/// </summary>
private STPStartInfo _stpStartInfoRW;
private STPStartInfo _stpStartInfo;
/// <summary>
/// Total number of work items that are stored in the work items queue
@@ -338,7 +277,7 @@ namespace Amib.Threading
/// A reference to the current work item a thread from the thread pool
/// is executing.
/// </summary>
private static ThreadEntry CurrentThreadEntry
internal static ThreadEntry CurrentThreadEntry
{
#if (WindowsCE)
get
@@ -369,7 +308,8 @@ namespace Amib.Threading
/// </summary>
public SmartThreadPool()
{
Initialize();
_stpStartInfo = new STPStartInfo();
Initialize();
}
/// <summary>
@@ -378,7 +318,10 @@ namespace Amib.Threading
/// <param name="idleTimeout">Idle timeout in milliseconds</param>
public SmartThreadPool(int idleTimeout)
{
_stpStartInfo.IdleTimeout = idleTimeout;
_stpStartInfo = new STPStartInfo
{
IdleTimeout = idleTimeout,
};
Initialize();
}
@@ -391,8 +334,11 @@ namespace Amib.Threading
int idleTimeout,
int maxWorkerThreads)
{
_stpStartInfo.IdleTimeout = idleTimeout;
_stpStartInfo.MaxWorkerThreads = maxWorkerThreads;
_stpStartInfo = new STPStartInfo
{
IdleTimeout = idleTimeout,
MaxWorkerThreads = maxWorkerThreads,
};
Initialize();
}
@@ -407,9 +353,12 @@ namespace Amib.Threading
int maxWorkerThreads,
int minWorkerThreads)
{
_stpStartInfo.IdleTimeout = idleTimeout;
_stpStartInfo.MaxWorkerThreads = maxWorkerThreads;
_stpStartInfo.MinWorkerThreads = minWorkerThreads;
_stpStartInfo = new STPStartInfo
{
IdleTimeout = idleTimeout,
MaxWorkerThreads = maxWorkerThreads,
MinWorkerThreads = minWorkerThreads,
};
Initialize();
}
@@ -428,11 +377,8 @@ namespace Amib.Threading
Name = "SmartThreadPool";
ValidateSTPStartInfo();
// _stpStartInfoRW holds a read/write reference to the original _stpStartInfo.
_stpStartInfoRW = _stpStartInfo;
// From now on _stpStartInfo is readonly
_stpStartInfo = _stpStartInfo.AsReadOnly();
// _stpStartInfoRW stores a read/write copy of the STPStartInfo.
// Actually only MaxWorkerThreads and MinWorkerThreads are overwritten
_isSuspended = _stpStartInfo.StartSuspended;
@@ -467,7 +413,7 @@ namespace Amib.Threading
private void StartOptimalNumberOfThreads()
{
int threadsCount = Math.Max(_workItemsQueue.Count, _stpStartInfo.MinWorkerThreads);
threadsCount = Math.Min(threadsCount, _stpStartInfo.MaxWorkerThreads);
threadsCount = Math.Min(threadsCount, _stpStartInfo.MaxWorkerThreads);
threadsCount -= _workerThreads.Count;
if (threadsCount > 0)
{
@@ -477,19 +423,19 @@ namespace Amib.Threading
private void ValidateSTPStartInfo()
{
if (_stpStartInfo.MinWorkerThreads < 0)
if (_stpStartInfo.MinWorkerThreads < 0)
{
throw new ArgumentOutOfRangeException(
"MinWorkerThreads", "MinWorkerThreads cannot be negative");
}
if (_stpStartInfo.MaxWorkerThreads <= 0)
if (_stpStartInfo.MaxWorkerThreads <= 0)
{
throw new ArgumentOutOfRangeException(
"MaxWorkerThreads", "MaxWorkerThreads must be greater than zero");
}
if (_stpStartInfo.MinWorkerThreads > _stpStartInfo.MaxWorkerThreads)
if (_stpStartInfo.MinWorkerThreads > _stpStartInfo.MaxWorkerThreads)
{
throw new ArgumentOutOfRangeException(
"MinWorkerThreads, maxWorkerThreads",
@@ -517,8 +463,8 @@ namespace Amib.Threading
/// </returns>
private WorkItem Dequeue()
{
WorkItem workItem =
_workItemsQueue.DequeueWorkItem(_stpStartInfo.IdleTimeout, _shuttingDownEvent);
WorkItem workItem =
_workItemsQueue.DequeueWorkItem(_stpStartInfo.IdleTimeout, _shuttingDownEvent);
return workItem;
}
@@ -628,7 +574,7 @@ namespace Amib.Threading
for(int i = 0; i < threadsCount; ++i)
{
// Don't create more threads then the upper limit
if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads)
if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads)
{
return;
}
@@ -639,7 +585,7 @@ namespace Amib.Threading
// Configure the new thread and start it
workerThread.Name = "STP " + Name + " Thread #" + _threadCounter;
workerThread.IsBackground = true;
workerThread.Priority = _stpStartInfo.ThreadPriority;
workerThread.Priority = _stpStartInfo.ThreadPriority;
workerThread.Start();
++_threadCounter;
@@ -703,11 +649,11 @@ namespace Amib.Threading
if (null == workItem)
{
// Double lock for quit.
if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
{
lock(_workerThreads.SyncRoot)
{
if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
{
// Inform that the thread is quiting and then quit.
// This method must be called within this lock or else
@@ -1180,7 +1126,7 @@ namespace Amib.Threading
/// <returns>A reference to the WorkItemsGroup</returns>
public IWorkItemsGroup CreateWorkItemsGroup(int concurrency)
{
IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, _stpStartInfo);
IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, _stpStartInfo);
return workItemsGroup;
}
@@ -1297,9 +1243,9 @@ namespace Amib.Threading
Debug.Assert(value <= _stpStartInfo.MaxWorkerThreads);
if (_stpStartInfo.MaxWorkerThreads < value)
{
_stpStartInfoRW.MaxWorkerThreads = value;
_stpStartInfo.MaxWorkerThreads = value;
}
_stpStartInfoRW.MinWorkerThreads = value;
_stpStartInfo.MinWorkerThreads = value;
StartOptimalNumberOfThreads();
}
}
@@ -1321,9 +1267,9 @@ namespace Amib.Threading
Debug.Assert(value >= _stpStartInfo.MinWorkerThreads);
if (_stpStartInfo.MinWorkerThreads > value)
{
_stpStartInfoRW.MinWorkerThreads = value;
_stpStartInfo.MinWorkerThreads = value;
}
_stpStartInfoRW.MaxWorkerThreads = value;
_stpStartInfo.MaxWorkerThreads = value;
StartOptimalNumberOfThreads();
}
}
@@ -1371,7 +1317,10 @@ namespace Amib.Threading
/// </summary>
public STPStartInfo STPStartInfo
{
get { return _stpStartInfo; }
get
{
return _stpStartInfo.AsReadOnly();
}
}
#endregion
@@ -1451,7 +1400,7 @@ namespace Amib.Threading
/// </summary>
public override WIGStartInfo WIGStartInfo
{
get { return _stpStartInfo; }
get { return _stpStartInfo.AsReadOnly(); }
}
/// <summary>
+4
View File
@@ -49,16 +49,20 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="WorkItem.WorkItemResult.cs" />
<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="STPPerformanceCounter.cs" />
<Compile Include="STPStartInfo.cs" />
<Compile Include="SynchronizedDictionary.cs" />
<Compile Include="SmartThreadPool.ThreadEntry.cs" />
<Compile Include="WIGStartInfo.cs" />
<Compile Include="WorkItem.cs" />
<Compile Include="WorkItemFactory.cs" />
+5 -1
View File
@@ -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>{D81DD596-C71F-4AC2-816C-63C19589E7E0}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -72,18 +72,22 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CallerThreadContext.cs" />
<Compile Include="CanceledWorkItemsGroup.cs" />
<Compile Include="EventWaitHandle.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="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" />
+148 -95
View File
@@ -7,116 +7,168 @@ namespace Amib.Threading
/// </summary>
public class WIGStartInfo
{
private bool _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
private bool _useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
private bool _disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
private CallToPostExecute _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
private WorkItemPriority _workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
private bool _startSuspended = SmartThreadPool.DefaultStartSuspended;
private bool _fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
private bool _useCallerCallContext;
private bool _useCallerHttpContext;
private bool _disposeOfStateObjects;
private CallToPostExecute _callToPostExecute;
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
private bool _startSuspended;
private WorkItemPriority _workItemPriority;
private bool _fillStateWithArgs;
public WIGStartInfo()
protected bool _readOnly;
public WIGStartInfo()
{
_fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
_startSuspended = SmartThreadPool.DefaultStartSuspended;
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
}
public WIGStartInfo(WIGStartInfo wigStartInfo)
public WIGStartInfo(WIGStartInfo wigStartInfo)
{
_useCallerCallContext = wigStartInfo._useCallerCallContext;
_useCallerHttpContext = wigStartInfo._useCallerHttpContext;
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
_callToPostExecute = wigStartInfo._callToPostExecute;
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
_workItemPriority = wigStartInfo._workItemPriority;
_startSuspended = wigStartInfo._startSuspended;
_fillStateWithArgs = wigStartInfo._fillStateWithArgs;
_useCallerCallContext = wigStartInfo.UseCallerCallContext;
_useCallerHttpContext = wigStartInfo.UseCallerHttpContext;
_disposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
_callToPostExecute = wigStartInfo.CallToPostExecute;
_postExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
_workItemPriority = wigStartInfo.WorkItemPriority;
_startSuspended = wigStartInfo.StartSuspended;
_fillStateWithArgs = wigStartInfo.FillStateWithArgs;
}
/// <summary>
/// Get/Set if to use the caller's security context
/// </summary>
public virtual bool UseCallerCallContext
{
get { return _useCallerCallContext; }
set { _useCallerCallContext = value; }
}
/// <summary>
/// Get/Set if to use the caller's HTTP context
/// </summary>
public virtual bool UseCallerHttpContext
{
get { return _useCallerHttpContext; }
set { _useCallerHttpContext = value; }
}
/// <summary>
/// Get/Set if to dispose of the state object of a work item
/// </summary>
public virtual bool DisposeOfStateObjects
{
get { return _disposeOfStateObjects; }
set { _disposeOfStateObjects = value; }
}
/// <summary>
/// Get/Set the run the post execute options
/// </summary>
public virtual CallToPostExecute CallToPostExecute
{
get { return _callToPostExecute; }
set { _callToPostExecute = value; }
}
/// <summary>
/// Get/Set the default post execute callback
/// </summary>
public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback
{
get { return _postExecuteWorkItemCallback; }
set { _postExecuteWorkItemCallback = value; }
}
/// <summary>
/// Get/Set if the work items execution should be suspended until the Start()
/// method is called.
/// </summary>
public virtual bool StartSuspended
{
get { return _startSuspended; }
set { _startSuspended = value; }
}
/// <summary>
/// Get/Set the default priority that a work item gets when it is enqueued
/// </summary>
public virtual WorkItemPriority WorkItemPriority
protected void ThrowIfReadOnly()
{
get { return _workItemPriority; }
set { _workItemPriority = value; }
if (_readOnly)
{
throw new NotSupportedException("This is a readonly instance and set is not supported");
}
}
/// <summary>
/// Get/Set the 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 virtual bool FillStateWithArgs
{
get { return _fillStateWithArgs; }
set { _fillStateWithArgs = value; }
}
/// <summary>
/// Get/Set if to use the caller's security context
/// </summary>
public virtual bool UseCallerCallContext
{
get { return _useCallerCallContext; }
set
{
ThrowIfReadOnly();
_useCallerCallContext = value;
}
}
/// <summary>
/// <summary>
/// Get/Set if to use the caller's HTTP context
/// </summary>
public virtual bool UseCallerHttpContext
{
get { return _useCallerHttpContext; }
set
{
ThrowIfReadOnly();
_useCallerHttpContext = value;
}
}
/// <summary>
/// Get/Set if to dispose of the state object of a work item
/// </summary>
public virtual bool DisposeOfStateObjects
{
get { return _disposeOfStateObjects; }
set
{
ThrowIfReadOnly();
_disposeOfStateObjects = value;
}
}
/// <summary>
/// Get/Set the run the post execute options
/// </summary>
public virtual CallToPostExecute CallToPostExecute
{
get { return _callToPostExecute; }
set
{
ThrowIfReadOnly();
_callToPostExecute = value;
}
}
/// <summary>
/// Get/Set the default post execute callback
/// </summary>
public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback
{
get { return _postExecuteWorkItemCallback; }
set
{
ThrowIfReadOnly();
_postExecuteWorkItemCallback = value;
}
}
/// <summary>
/// Get/Set if the work items execution should be suspended until the Start()
/// method is called.
/// </summary>
public virtual bool StartSuspended
{
get { return _startSuspended; }
set
{
ThrowIfReadOnly();
_startSuspended = value;
}
}
/// <summary>
/// Get/Set the default priority that a work item gets when it is enqueued
/// </summary>
public virtual WorkItemPriority WorkItemPriority
{
get { return _workItemPriority; }
set { _workItemPriority = value; }
}
/// <summary>
/// Get/Set the 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 virtual bool FillStateWithArgs
{
get { return _fillStateWithArgs; }
set
{
ThrowIfReadOnly();
_fillStateWithArgs = value;
}
}
/// <summary>
/// Get a readonly version of this WIGStartInfo
/// </summary>
/// <returns>Returns a readonly reference to this WIGStartInfoRO</returns>
public WIGStartInfo AsReadOnly()
{
return new WIGStartInfoRO(this);
}
#region WIGStartInfoRO class
{
return new WIGStartInfo(this) { _readOnly = true };
}
/*
#region WIGStartInfoRO class
/// <summary>
/// A readonly version of WIGStartInfo
@@ -206,5 +258,6 @@ namespace Amib.Threading
}
}
#endregion
*/
}
}
+190
View File
@@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Amib.Threading.Internal
{
public partial class WorkItem
{
#region WorkItemResult class
private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult, IInternalWaitableResult
{
/// <summary>
/// A back reference to the work item
/// </summary>
private readonly WorkItem _workItem;
public WorkItemResult(WorkItem workItem)
{
_workItem = workItem;
}
internal WorkItem GetWorkItem()
{
return _workItem;
}
#region IWorkItemResult Members
public bool IsCompleted
{
get
{
return _workItem.IsCompleted;
}
}
public bool IsCanceled
{
get
{
return _workItem.IsCanceled;
}
}
public object GetResult()
{
return _workItem.GetResult(Timeout.Infinite, true, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null);
}
public object GetResult(TimeSpan timeout, bool exitContext)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
}
public object GetResult(out Exception e)
{
return _workItem.GetResult(Timeout.Infinite, true, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
}
public bool Cancel()
{
return Cancel(false);
}
public bool Cancel(bool abortExecution)
{
return _workItem.Cancel(abortExecution);
}
public object State
{
get
{
return _workItem._state;
}
}
public WorkItemPriority WorkItemPriority
{
get
{
return _workItem._workItemInfo.WorkItemPriority;
}
}
/// <summary>
/// Return the result, same as GetResult()
/// </summary>
public object Result
{
get { return GetResult(); }
}
/// <summary>
/// Returns the exception if occured otherwise returns null.
/// This value is valid only after the work item completed,
/// before that it is always null.
/// </summary>
public object Exception
{
get { return _workItem._exception; }
}
#endregion
#region IInternalWorkItemResult Members
public event WorkItemStateCallback OnWorkItemStarted
{
add
{
_workItem.OnWorkItemStarted += value;
}
remove
{
_workItem.OnWorkItemStarted -= value;
}
}
public event WorkItemStateCallback OnWorkItemCompleted
{
add
{
_workItem.OnWorkItemCompleted += value;
}
remove
{
_workItem.OnWorkItemCompleted -= value;
}
}
#endregion
#region IInternalWorkItemResult Members
public IWorkItemResult GetWorkItemResult()
{
return this;
}
public IWorkItemResult<TResult> GetWorkItemResultT<TResult>()
{
return new WorkItemResultTWrapper<TResult>(this);
}
#endregion
}
#endregion
}
}
+11 -242
View File
@@ -4,68 +4,10 @@ using System.Diagnostics;
namespace Amib.Threading.Internal
{
#region WorkItem Delegate
/// <summary>
/// An internal delegate to call when the WorkItem starts or completes
/// </summary>
internal delegate void WorkItemStateCallback(WorkItem workItem);
#endregion
#region CanceledWorkItemsGroup class
public class CanceledWorkItemsGroup
{
public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
private bool _isCanceled = false;
public bool IsCanceled
{
get { return _isCanceled; }
set { _isCanceled = value; }
}
}
#endregion
#region IInternalWorkItemResult interface
internal interface IInternalWorkItemResult
{
event WorkItemStateCallback OnWorkItemStarted;
event WorkItemStateCallback OnWorkItemCompleted;
}
#endregion
#region IInternalWaitableResult interface
internal interface IInternalWaitableResult
{
/// <summary>
/// This method is intent for internal use.
/// </summary>
IWorkItemResult GetWorkItemResult();
}
#endregion
#region IHasWorkItemPriority interface
public interface IHasWorkItemPriority
{
WorkItemPriority WorkItemPriority { get; }
}
#endregion
#region WorkItem class
/// <summary>
/// Holds a callback delegate and the state for that delegate.
/// </summary>
public class WorkItem : IHasWorkItemPriority
public partial class WorkItem : IHasWorkItemPriority
{
#region WorkItemState enum
@@ -236,6 +178,14 @@ namespace Amib.Threading.Internal
}
}
internal WorkItemInfo WorkItemInfo
{
get
{
return _workItemInfo;
}
}
#endregion
#region Construction
@@ -292,13 +242,13 @@ namespace Amib.Threading.Internal
#region Methods
public CanceledWorkItemsGroup CanceledWorkItemsGroup
internal CanceledWorkItemsGroup CanceledWorkItemsGroup
{
get { return _canceledWorkItemsGroup; }
set { _canceledWorkItemsGroup = value; }
}
public CanceledWorkItemsGroup CanceledSmartThreadPool
internal CanceledWorkItemsGroup CanceledSmartThreadPool
{
get { return _canceledSmartThreadPool; }
set { _canceledSmartThreadPool = value; }
@@ -994,186 +944,6 @@ namespace Amib.Threading.Internal
}
}
#region WorkItemResult class
private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult, IInternalWaitableResult
{
/// <summary>
/// A back reference to the work item
/// </summary>
private readonly WorkItem _workItem;
public WorkItemResult(WorkItem workItem)
{
_workItem = workItem;
}
internal WorkItem GetWorkItem()
{
return _workItem;
}
#region IWorkItemResult Members
public bool IsCompleted
{
get
{
return _workItem.IsCompleted;
}
}
public bool IsCanceled
{
get
{
return _workItem.IsCanceled;
}
}
public object GetResult()
{
return _workItem.GetResult(Timeout.Infinite, true, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null);
}
public object GetResult(TimeSpan timeout, bool exitContext)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
}
public object GetResult(out Exception e)
{
return _workItem.GetResult(Timeout.Infinite, true, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
}
public bool Cancel()
{
return Cancel(false);
}
public bool Cancel(bool abortExecution)
{
return _workItem.Cancel(abortExecution);
}
public object State
{
get
{
return _workItem._state;
}
}
public WorkItemPriority WorkItemPriority
{
get
{
return _workItem._workItemInfo.WorkItemPriority;
}
}
/// <summary>
/// Return the result, same as GetResult()
/// </summary>
public object Result
{
get { return GetResult(); }
}
/// <summary>
/// Returns the exception if occured otherwise returns null.
/// This value is valid only after the work item completed,
/// before that it is always null.
/// </summary>
public object Exception
{
get { return _workItem._exception; }
}
#endregion
#region IInternalWorkItemResult Members
public event WorkItemStateCallback OnWorkItemStarted
{
add
{
_workItem.OnWorkItemStarted += value;
}
remove
{
_workItem.OnWorkItemStarted -= value;
}
}
public event WorkItemStateCallback OnWorkItemCompleted
{
add
{
_workItem.OnWorkItemCompleted += value;
}
remove
{
_workItem.OnWorkItemCompleted -= value;
}
}
#endregion
#region IInternalWorkItemResult Members
public IWorkItemResult GetWorkItemResult()
{
return this;
}
public IWorkItemResult<TResult> GetWorkItemResultT<TResult>()
{
return new WorkItemResultTWrapper<TResult>(this);
}
#endregion
}
#endregion
public void DisposeOfState()
{
if (_workItemInfo.DisposeOfStateObjects)
@@ -1187,5 +957,4 @@ namespace Amib.Threading.Internal
}
}
}
#endregion
}
+37 -92
View File
@@ -7,110 +7,55 @@ namespace Amib.Threading
/// </summary>
public class WorkItemInfo
{
/// <summary>
/// Use the caller's security context
/// </summary>
private bool _useCallerCallContext;
/// <summary>
/// Use the caller's security context
/// </summary>
private bool _useCallerHttpContext;
/// <summary>
/// Dispose of the state object of a work item
/// </summary>
private bool _disposeOfStateObjects;
/// <summary>
/// The option to run the post execute
/// </summary>
private CallToPostExecute _callToPostExecute;
/// <summary>
/// A post execute callback to call when none is provided in
/// the QueueWorkItem method.
/// </summary>
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
/// <summary>
/// The priority of the work item
/// </summary>
private WorkItemPriority _workItemPriority;
public WorkItemInfo()
public WorkItemInfo()
{
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
UseCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
UseCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
DisposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
CallToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
PostExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
WorkItemPriority = SmartThreadPool.DefaultWorkItemPriority;
}
public WorkItemInfo(WorkItemInfo workItemInfo)
{
_useCallerCallContext = workItemInfo._useCallerCallContext;
_useCallerHttpContext = workItemInfo._useCallerHttpContext;
_disposeOfStateObjects = workItemInfo._disposeOfStateObjects;
_callToPostExecute = workItemInfo._callToPostExecute;
_postExecuteWorkItemCallback = workItemInfo._postExecuteWorkItemCallback;
_workItemPriority = workItemInfo._workItemPriority;
UseCallerCallContext = workItemInfo.UseCallerCallContext;
UseCallerHttpContext = workItemInfo.UseCallerHttpContext;
DisposeOfStateObjects = workItemInfo.DisposeOfStateObjects;
CallToPostExecute = workItemInfo.CallToPostExecute;
PostExecuteWorkItemCallback = workItemInfo.PostExecuteWorkItemCallback;
WorkItemPriority = workItemInfo.WorkItemPriority;
}
/// <summary>
/// Get/Set if to use the caller's security context
/// </summary>
public bool UseCallerCallContext
{
get { return _useCallerCallContext; }
set { _useCallerCallContext = value; }
}
/// <summary>
/// Get/Set if to use the caller's security context
/// </summary>
public bool UseCallerCallContext { get; set; }
/// <summary>
/// Get/Set if to use the caller's HTTP context
/// </summary>
public bool UseCallerHttpContext
{
get { return _useCallerHttpContext; }
set { _useCallerHttpContext = value; }
}
/// <summary>
/// Get/Set if to use the caller's HTTP context
/// </summary>
public bool UseCallerHttpContext { get; set; }
/// <summary>
/// Get/Set if to dispose of the state object of a work item
/// </summary>
public bool DisposeOfStateObjects
{
get { return _disposeOfStateObjects; }
set { _disposeOfStateObjects = value; }
}
/// <summary>
/// Get/Set if to dispose of the state object of a work item
/// </summary>
public bool DisposeOfStateObjects { get; set; }
/// <summary>
/// Get/Set the run the post execute options
/// </summary>
public CallToPostExecute CallToPostExecute
{
get { return _callToPostExecute; }
set { _callToPostExecute = value; }
}
/// <summary>
/// Get/Set the run the post execute options
/// </summary>
public CallToPostExecute CallToPostExecute { get; set; }
/// <summary>
/// Get/Set the post execute callback
/// </summary>
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
{
get { return _postExecuteWorkItemCallback; }
set { _postExecuteWorkItemCallback = value; }
}
/// <summary>
/// Get/Set the post execute callback
/// </summary>
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback { get; set; }
/// <summary>
/// Get/Set the work items priority
/// </summary>
public WorkItemPriority WorkItemPriority
{
get { return _workItemPriority; }
set { _workItemPriority = value; }
}
/// <summary>
/// Get/Set the work items priority
/// </summary>
public WorkItemPriority WorkItemPriority { get; set; }
}
#endregion
+18 -23
View File
@@ -13,11 +13,10 @@ namespace Amib.Threading.Internal
/// </summary>
private string _name = "WorkItemsGroupBase";
/// <summary>
/// Inidcates if the SmartThreadPool/WorkItemsGroup is idle.
/// Its value is true if the _isIdleWaitHandle is set.
/// </summary>
private bool _isIdle = true;
public WorkItemsGroupBase()
{
IsIdle = true;
}
#endregion
@@ -82,11 +81,7 @@ namespace Amib.Threading.Internal
/// <summary>
/// IsIdle is true when there are no work items running or queued.
/// </summary>
public bool IsIdle
{
get { return _isIdle; }
protected set { _isIdle = value; }
}
public bool IsIdle { get; protected set; }
#endregion
@@ -302,11 +297,11 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
{
action.Invoke(arg);
return null;
},
state =>
{
action.Invoke(arg);
return null;
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null);
Enqueue(workItem);
return workItem.GetWorkItemResult();
@@ -318,7 +313,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
action.Invoke(arg1, arg2);
return null;
@@ -334,7 +329,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
action.Invoke(arg1, arg2, arg3);
return null;
@@ -351,7 +346,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
action.Invoke(arg1, arg2, arg3, arg4);
return null;
@@ -371,7 +366,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
return func.Invoke();
});
@@ -385,7 +380,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
return func.Invoke(arg);
},
@@ -400,7 +395,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
return func.Invoke(arg1, arg2);
},
@@ -416,7 +411,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
return func.Invoke(arg1, arg2, arg3);
},
@@ -432,7 +427,7 @@ namespace Amib.Threading.Internal
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
delegate
state =>
{
return func.Invoke(arg1, arg2, arg3, arg4);
},
-44
View File
@@ -1,11 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// 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("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -14,45 +8,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// 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.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
-44
View File
@@ -1,11 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
//
// 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("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -14,45 +8,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// 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.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
+16 -23
View File
@@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.Reflection;
using System.Drawing.Imaging;
namespace UsageControl
@@ -40,9 +34,8 @@ namespace UsageControl
{
//Debug.WriteLine("GenerateItemImage");
Bitmap itemImage = null;
Rectangle rc = new Rectangle(0, 0, width, height);
itemImage = new Bitmap(rc.Width, rc.Height);
Bitmap itemImage = new Bitmap(rc.Width, rc.Height);
/// Create button
rc.Inflate(-3, -3);
@@ -90,11 +83,11 @@ namespace UsageControl
{
//Debug.WriteLine("GetItemsImage");
Bitmap itemImage = null;
Bitmap itemImage;
if (!_imagesCache.ContainsKey(color))
{
Rectangle rc = new Rectangle(0, 0, this.Width, _itemHeight);
Rectangle rc = new Rectangle(0, 0, Width, _itemHeight);
itemImage = new Bitmap(rc.Width, rc.Height);
/// Create button
@@ -120,7 +113,7 @@ namespace UsageControl
GraphicsPath path3 = GetPath(rc3, rc3.Height);
LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
itemImage = new Bitmap(this.Width - 2, _itemHeight);
itemImage = new Bitmap(Width - 2, _itemHeight);
Graphics g = Graphics.FromImage(itemImage);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillPath(br2, path2);
@@ -140,12 +133,12 @@ namespace UsageControl
//Debug.WriteLine("EnableDoubleBuffering");
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.SupportsTransparentBackColor,
true);
this.UpdateStyles();
UpdateStyles();
}
public void Reset()
@@ -245,7 +238,7 @@ namespace UsageControl
text = "(" + (_queuedItems.Count - _maxItemsVisible) + ")...";
}
SizeF size = g.MeasureString(entry.Text, this.Font);
SizeF size = g.MeasureString(entry.Text, Font);
//Debug.WriteLine(size.Width);
Bitmap itemImage = GetItemsImage(entry.Color);
@@ -256,7 +249,7 @@ namespace UsageControl
g.DrawImage(itemImage, -1, slot.Top-2);
//g.DrawString(text, this.Font, Brushes.Black, new RectangleF((this.Width - size.Width) / 2, top + 2, this.Width, bottom));
g.DrawString(text, this.Font, Brushes.Black, slot);
g.DrawString(text, Font, Brushes.Black, slot);
++i;
}
@@ -282,15 +275,15 @@ namespace UsageControl
private void ControlRezised()
{
//Debug.WriteLine("ControlRezised");
Graphics g = Graphics.FromHwnd(this.Handle);
SizeF size = g.MeasureString("X", this.Font);
Graphics g = Graphics.FromHwnd(Handle);
SizeF size = g.MeasureString("X", Font);
g.Dispose();
_itemHeight = (int)size.Height + 5;
_maxItemsVisible = this.Height / _itemHeight - 1;
_maxItemsVisible = Height / _itemHeight - 1;
_lastVisibleItemIndex = _maxItemsVisible;
_imagesCache = new Dictionary<Color, Bitmap>();
Rectangle border = new Rectangle(0, 0, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
Rectangle border = new Rectangle(0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
_pathBorder = GetPath(border, 20);
PrepareSlots();
@@ -303,8 +296,8 @@ namespace UsageControl
_slots = new RectangleF[_maxItemsVisible+5];
for (int i = 0; i < _slots.Length; i++)
{
int top = 0;
int bottom = 0;
int top;
int bottom;
if (topdown)
{
bottom = 1;
@@ -314,13 +307,13 @@ namespace UsageControl
}
else
{
bottom = this.Height - 1;
bottom = Height - 1;
top = bottom;
bottom -= i * _itemHeight;
top -= (i + 1) * _itemHeight;
}
_slots[i] = new RectangleF((this.Width - 55) / 2, top + 2, this.Width, bottom);
_slots[i] = new RectangleF((Width - 55) / 2, top + 2, Width, bottom);
}
}
+6 -23
View File
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace UsageControl
@@ -9,10 +6,6 @@ namespace UsageControl
{
public class QueueUsageEntry
{
private string _text;
private Color _color;
private bool _isExecuting;
public QueueUsageEntry(
string text,
Color color) : this (text, color, false)
@@ -24,26 +17,16 @@ namespace UsageControl
Color color,
bool blink)
{
_text = text;
_color = color;
_isExecuting = blink;
Text = text;
Color = color;
IsExecuting = blink;
}
public Color Color
{
get { return _color; }
}
public Color Color { get; private set; }
public string Text
{
get { return _text; }
}
public string Text { get; private set; }
public bool IsExecuting
{
get { return _isExecuting; }
set { _isExecuting = value; }
}
public bool IsExecuting { get; set; }
}
}
}
+6 -8
View File
@@ -1,8 +1,6 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace UsageControl
@@ -10,12 +8,12 @@ namespace UsageControl
/// <summary>
/// Summary description for UsageHistoryControl.
/// </summary>
public class UsageHistoryControl : System.Windows.Forms.UserControl
public class UsageHistoryControl : UserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private Container components = null;
private const int squareWidth = 12;
private const int maxLastValuesCount = 2000;
@@ -83,17 +81,17 @@ namespace UsageControl
private void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
UpdateStyles();
}
protected override void OnResize(EventArgs e)
{
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
@@ -183,7 +181,7 @@ namespace UsageControl
max = value;
// Invalidate the control to get a repaint.
this.Invalidate();
Invalidate();
}
}
+1 -4
View File
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using UsageControl;
using Amib.Threading;
@@ -180,7 +177,7 @@ namespace WorkItemsGroupDemo
{
lblStatus6.Text = _stp.IsIdle ? "Idle" : "Working";
object [] statesWorking = null;
object[] statesWorking;
lock (_workingStates.SyncRoot)
{
statesWorking = new object[_workingStates.Count];
-1
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WorkItemsGroupDemo
@@ -1,10 +1,6 @@
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("WindowsApplication1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
@@ -13,21 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2006")]
[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("68872ba4-6524-406b-9c96-cf8ca3f4c729")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]