Merge branch 'master' into careminster
Conflicts: ThirdParty/SmartThreadPool/SmartThreadPool.csavinationmerge
commit
8c5445b774
|
@ -158,7 +158,7 @@ namespace OpenSim.Framework.Capabilities
|
||||||
/// capabilities and their handler details.
|
/// capabilities and their handler details.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
/// <param name="excludeSeed">If true, then exclude the seed cap.</param>
|
||||||
public Hashtable GetCapsDetails(bool excludeSeed)
|
public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
|
||||||
{
|
{
|
||||||
Hashtable caps = new Hashtable();
|
Hashtable caps = new Hashtable();
|
||||||
string protocol = "http://";
|
string protocol = "http://";
|
||||||
|
@ -175,6 +175,9 @@ namespace OpenSim.Framework.Capabilities
|
||||||
if (excludeSeed && "SEED" == capsName)
|
if (excludeSeed && "SEED" == capsName)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (requestedCaps != null && !requestedCaps.Contains(capsName))
|
||||||
|
continue;
|
||||||
|
|
||||||
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
|
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,4 +185,4 @@ namespace OpenSim.Framework.Capabilities
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1852,7 +1852,7 @@ namespace OpenSim.Framework
|
||||||
case FireAndForgetMethod.SmartThreadPool:
|
case FireAndForgetMethod.SmartThreadPool:
|
||||||
if (m_ThreadPool == null)
|
if (m_ThreadPool == null)
|
||||||
InitThreadPool(15);
|
InitThreadPool(15);
|
||||||
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj });
|
m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
|
||||||
break;
|
break;
|
||||||
case FireAndForgetMethod.Thread:
|
case FireAndForgetMethod.Thread:
|
||||||
Thread thread = new Thread(delegate(object o) { realCallback(o); });
|
Thread thread = new Thread(delegate(object o) { realCallback(o); });
|
||||||
|
@ -1922,15 +1922,15 @@ namespace OpenSim.Framework
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object SmartThreadPoolCallback(object o)
|
// private static object SmartThreadPoolCallback(object o)
|
||||||
{
|
// {
|
||||||
object[] array = (object[])o;
|
// object[] array = (object[])o;
|
||||||
WaitCallback callback = (WaitCallback)array[0];
|
// WaitCallback callback = (WaitCallback)array[0];
|
||||||
object obj = array[1];
|
// object obj = array[1];
|
||||||
|
//
|
||||||
callback(obj);
|
// callback(obj);
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#endregion FireAndForget Threading Pattern
|
#endregion FireAndForget Threading Pattern
|
||||||
|
|
||||||
|
|
|
@ -355,11 +355,22 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true);
|
OSDArray capsRequested = (OSDArray)OSDParser.DeserializeLLSDXml(request);
|
||||||
|
List<string> validCaps = new List<string>();
|
||||||
|
|
||||||
|
foreach (OSD c in capsRequested)
|
||||||
|
validCaps.Add(c.AsString());
|
||||||
|
|
||||||
|
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps);
|
||||||
|
|
||||||
// Add the external too
|
// Add the external too
|
||||||
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
|
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
|
||||||
|
{
|
||||||
|
if (!validCaps.Contains(kvp.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
caps[kvp.Key] = kvp.Value;
|
caps[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
string result = LLSDHelpers.SerialiseLLSDReply(caps);
|
string result = LLSDHelpers.SerialiseLLSDReply(caps);
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Framework
|
||||||
{
|
{
|
||||||
caps.AppendFormat("** Circuit {0}:\n", kvp.Key);
|
caps.AppendFormat("** Circuit {0}:\n", kvp.Key);
|
||||||
|
|
||||||
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); )
|
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
|
||||||
{
|
{
|
||||||
Uri uri = new Uri(kvp2.Value.ToString());
|
Uri uri = new Uri(kvp2.Value.ToString());
|
||||||
caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
|
caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
|
||||||
|
|
|
@ -676,11 +676,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (remoteClient == null || so.OwnerID != remoteClient.AgentId)
|
if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId)
|
||||||
{
|
{
|
||||||
// Taking copy of another person's item. Take to
|
// Taking copy of another person's item. Take to
|
||||||
// Objects folder.
|
// Objects folder.
|
||||||
folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
|
folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
|
||||||
|
so.FromFolderID = UUID.Zero;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -696,7 +697,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
//
|
//
|
||||||
if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
|
if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
|
||||||
{
|
{
|
||||||
if (so.FromFolderID != UUID.Zero && userID == remoteClient.AgentId)
|
if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
|
||||||
{
|
{
|
||||||
InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
|
InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
|
||||||
if (f != null)
|
if (f != null)
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
public interface IScriptWorkItem
|
public interface IScriptWorkItem
|
||||||
{
|
{
|
||||||
bool Cancel();
|
bool Cancel();
|
||||||
void Abort();
|
bool Abort();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wait for the work item to complete.
|
/// Wait for the work item to complete.
|
||||||
|
|
|
@ -572,9 +572,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
|
|
||||||
public bool Stop(int timeout)
|
public bool Stop(int timeout)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
if (DebugLevel >= 1)
|
||||||
// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
|
m_log.DebugFormat(
|
||||||
// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
|
"[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
|
||||||
|
ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
|
||||||
|
|
||||||
IScriptWorkItem workItem;
|
IScriptWorkItem workItem;
|
||||||
|
|
||||||
|
|
|
@ -551,7 +551,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
/// <param name="instance"></param>
|
/// <param name="instance"></param>
|
||||||
/// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
|
/// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
|
||||||
private void HandleScriptsAction<TKey>(
|
private void HandleScriptsAction<TKey>(
|
||||||
string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
|
string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector)
|
||||||
{
|
{
|
||||||
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
|
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
|
||||||
return;
|
return;
|
||||||
|
@ -1599,7 +1599,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
startInfo.MaxWorkerThreads = maxThreads;
|
startInfo.MaxWorkerThreads = maxThreads;
|
||||||
startInfo.MinWorkerThreads = minThreads;
|
startInfo.MinWorkerThreads = minThreads;
|
||||||
startInfo.ThreadPriority = threadPriority;;
|
startInfo.ThreadPriority = threadPriority;;
|
||||||
startInfo.StackSize = stackSize;
|
startInfo.MaxStackSize = stackSize;
|
||||||
startInfo.StartSuspended = true;
|
startInfo.StartSuspended = true;
|
||||||
|
|
||||||
m_ThreadPool = new SmartThreadPool(startInfo);
|
m_ThreadPool = new SmartThreadPool(startInfo);
|
||||||
|
|
|
@ -52,16 +52,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
return wr.Cancel();
|
return wr.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Abort()
|
public bool Abort()
|
||||||
{
|
{
|
||||||
wr.Abort();
|
return wr.Cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Wait(int t)
|
public bool Wait(int t)
|
||||||
{
|
{
|
||||||
// We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
|
// We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
|
||||||
// TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
|
// TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
|
||||||
// int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8
|
// int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8
|
||||||
// (or very likely other versions of Mono at least up until 3.0.3).
|
// (or very likely other versions of Mono at least up until 3.0.3).
|
||||||
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
|
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
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("")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("")]
|
|
||||||
[assembly: AssemblyCopyright("")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
[assembly: CLSCompliant(true)]
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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("0.7.6.*")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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,223 +1,138 @@
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
using System.Threading;
|
|
||||||
using System.Reflection;
|
using System;
|
||||||
using System.Web;
|
using System.Diagnostics;
|
||||||
using System.Runtime.Remoting.Messaging;
|
using System.Threading;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Web;
|
||||||
namespace Amib.Threading
|
using System.Runtime.Remoting.Messaging;
|
||||||
{
|
|
||||||
#region CallerThreadContext class
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
/// <summary>
|
{
|
||||||
/// This class stores the caller call context in order to restore
|
#region CallerThreadContext class
|
||||||
/// it when the work item is executed in the thread pool environment.
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
internal class CallerThreadContext
|
/// This class stores the caller call context in order to restore
|
||||||
{
|
/// it when the work item is executed in the thread pool environment.
|
||||||
#region Prepare reflection information
|
/// </summary>
|
||||||
|
internal class CallerThreadContext
|
||||||
// Cached type information.
|
{
|
||||||
private static MethodInfo getLogicalCallContextMethodInfo =
|
#region Prepare reflection information
|
||||||
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
|
// Cached type information.
|
||||||
private static MethodInfo setLogicalCallContextMethodInfo =
|
private static readonly MethodInfo getLogicalCallContextMethodInfo =
|
||||||
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
private static string HttpContextSlotName = GetHttpContextSlotName();
|
private static readonly MethodInfo setLogicalCallContextMethodInfo =
|
||||||
|
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
private static string GetHttpContextSlotName()
|
|
||||||
{
|
private static string HttpContextSlotName = GetHttpContextSlotName();
|
||||||
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
|
|
||||||
|
private static string GetHttpContextSlotName()
|
||||||
if( fi != null )
|
{
|
||||||
return (string)fi.GetValue(null);
|
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
else // Use the default "HttpContext" slot name
|
|
||||||
return "HttpContext";
|
if (fi != null)
|
||||||
}
|
{
|
||||||
|
return (string) fi.GetValue(null);
|
||||||
#endregion
|
}
|
||||||
|
|
||||||
#region Private fields
|
return "HttpContext";
|
||||||
|
}
|
||||||
private HttpContext _httpContext = null;
|
|
||||||
private LogicalCallContext _callContext = null;
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#region Private fields
|
||||||
|
|
||||||
/// <summary>
|
private HttpContext _httpContext;
|
||||||
/// Constructor
|
private LogicalCallContext _callContext;
|
||||||
/// </summary>
|
|
||||||
private CallerThreadContext()
|
#endregion
|
||||||
{
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
public bool CapturedCallContext
|
/// </summary>
|
||||||
{
|
private CallerThreadContext()
|
||||||
get
|
{
|
||||||
{
|
}
|
||||||
return (null != _callContext);
|
|
||||||
}
|
public bool CapturedCallContext
|
||||||
}
|
{
|
||||||
|
get
|
||||||
public bool CapturedHttpContext
|
{
|
||||||
{
|
return (null != _callContext);
|
||||||
get
|
}
|
||||||
{
|
}
|
||||||
return (null != _httpContext);
|
|
||||||
}
|
public bool CapturedHttpContext
|
||||||
}
|
{
|
||||||
|
get
|
||||||
/// <summary>
|
{
|
||||||
/// Captures the current thread context
|
return (null != _httpContext);
|
||||||
/// </summary>
|
}
|
||||||
/// <returns></returns>
|
}
|
||||||
public static CallerThreadContext Capture(
|
|
||||||
bool captureCallContext,
|
/// <summary>
|
||||||
bool captureHttpContext)
|
/// Captures the current thread context
|
||||||
{
|
/// </summary>
|
||||||
Debug.Assert(captureCallContext || captureHttpContext);
|
/// <returns></returns>
|
||||||
|
public static CallerThreadContext Capture(
|
||||||
CallerThreadContext callerThreadContext = new CallerThreadContext();
|
bool captureCallContext,
|
||||||
|
bool captureHttpContext)
|
||||||
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
|
{
|
||||||
// Capture Call Context
|
Debug.Assert(captureCallContext || captureHttpContext);
|
||||||
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
|
|
||||||
{
|
CallerThreadContext callerThreadContext = new CallerThreadContext();
|
||||||
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
|
|
||||||
if (callerThreadContext._callContext != null)
|
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
|
||||||
{
|
// Capture Call Context
|
||||||
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
|
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
|
||||||
}
|
{
|
||||||
}
|
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
|
||||||
|
if (callerThreadContext._callContext != null)
|
||||||
// Capture httpContext
|
{
|
||||||
if (captureHttpContext && (null != HttpContext.Current))
|
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
|
||||||
{
|
}
|
||||||
callerThreadContext._httpContext = HttpContext.Current;
|
}
|
||||||
}
|
|
||||||
|
// Capture httpContext
|
||||||
return callerThreadContext;
|
if (captureHttpContext && (null != HttpContext.Current))
|
||||||
}
|
{
|
||||||
|
callerThreadContext._httpContext = HttpContext.Current;
|
||||||
/// <summary>
|
}
|
||||||
/// Applies the thread context stored earlier
|
|
||||||
/// </summary>
|
return callerThreadContext;
|
||||||
/// <param name="callerThreadContext"></param>
|
}
|
||||||
public static void Apply(CallerThreadContext callerThreadContext)
|
|
||||||
{
|
/// <summary>
|
||||||
if (null == callerThreadContext)
|
/// Applies the thread context stored earlier
|
||||||
{
|
/// </summary>
|
||||||
throw new ArgumentNullException("callerThreadContext");
|
/// <param name="callerThreadContext"></param>
|
||||||
}
|
public static void Apply(CallerThreadContext callerThreadContext)
|
||||||
|
{
|
||||||
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
|
if (null == callerThreadContext)
|
||||||
// Restore call context
|
{
|
||||||
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
|
throw new ArgumentNullException("callerThreadContext");
|
||||||
{
|
}
|
||||||
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
|
|
||||||
}
|
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
|
||||||
|
// Restore call context
|
||||||
// Restore HttpContext
|
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
|
||||||
if (callerThreadContext._httpContext != null)
|
{
|
||||||
{
|
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
|
||||||
CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
|
}
|
||||||
}
|
|
||||||
}
|
// Restore HttpContext
|
||||||
}
|
if (callerThreadContext._httpContext != null)
|
||||||
|
{
|
||||||
#endregion
|
HttpContext.Current = callerThreadContext._httpContext;
|
||||||
|
//CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
|
||||||
// Ami Bar
|
#endregion
|
||||||
// amibar@gmail.com
|
}
|
||||||
|
#endif
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.Remoting.Contexts;
|
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
|
||||||
{
|
|
||||||
#region CallerThreadContext class
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This class stores the caller thread context in order to restore
|
|
||||||
/// it when the work item is executed in the context of the thread
|
|
||||||
/// from the pool.
|
|
||||||
/// Note that we can't store the thread's CompressedStack, because
|
|
||||||
/// it throws a security exception
|
|
||||||
/// </summary>
|
|
||||||
public class CallerThreadContext
|
|
||||||
{
|
|
||||||
private CultureInfo _culture = null;
|
|
||||||
private CultureInfo _cultureUI = null;
|
|
||||||
private IPrincipal _principal;
|
|
||||||
private System.Runtime.Remoting.Contexts.Context _context;
|
|
||||||
|
|
||||||
private static FieldInfo _fieldInfo = GetFieldInfo();
|
|
||||||
|
|
||||||
private static FieldInfo GetFieldInfo()
|
|
||||||
{
|
|
||||||
Type threadType = typeof(Thread);
|
|
||||||
return threadType.GetField(
|
|
||||||
"m_Context",
|
|
||||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
private CallerThreadContext()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Captures the current thread context
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static CallerThreadContext Capture()
|
|
||||||
{
|
|
||||||
CallerThreadContext callerThreadContext = new CallerThreadContext();
|
|
||||||
|
|
||||||
Thread thread = Thread.CurrentThread;
|
|
||||||
callerThreadContext._culture = thread.CurrentCulture;
|
|
||||||
callerThreadContext._cultureUI = thread.CurrentUICulture;
|
|
||||||
callerThreadContext._principal = Thread.CurrentPrincipal;
|
|
||||||
callerThreadContext._context = Thread.CurrentContext;
|
|
||||||
return callerThreadContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies the thread context stored earlier
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="callerThreadContext"></param>
|
|
||||||
public static void Apply(CallerThreadContext callerThreadContext)
|
|
||||||
{
|
|
||||||
Thread thread = Thread.CurrentThread;
|
|
||||||
thread.CurrentCulture = callerThreadContext._culture;
|
|
||||||
thread.CurrentUICulture = callerThreadContext._cultureUI;
|
|
||||||
Thread.CurrentPrincipal = callerThreadContext._principal;
|
|
||||||
|
|
||||||
// Uncomment the following block to enable the Thread.CurrentThread
|
|
||||||
/*
|
|
||||||
if (null != _fieldInfo)
|
|
||||||
{
|
|
||||||
_fieldInfo.SetValue(
|
|
||||||
Thread.CurrentThread,
|
|
||||||
callerThreadContext._context);
|
|
||||||
}
|
|
||||||
* /
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
#if (_WINDOWS_CE)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// EventWaitHandle class
|
||||||
|
/// In WindowsCE this class doesn't exist and I needed the WaitAll and WaitAny implementation.
|
||||||
|
/// So I wrote this class to implement these two methods with some of their overloads.
|
||||||
|
/// It uses the WaitForMultipleObjects API to do the WaitAll and WaitAny.
|
||||||
|
/// Note that this class doesn't even inherit from WaitHandle!
|
||||||
|
/// </summary>
|
||||||
|
public class STPEventWaitHandle
|
||||||
|
{
|
||||||
|
#region Public Constants
|
||||||
|
|
||||||
|
public const int WaitTimeout = Timeout.Infinite;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private External Constants
|
||||||
|
|
||||||
|
private const Int32 WAIT_FAILED = -1;
|
||||||
|
private const Int32 WAIT_TIMEOUT = 0x102;
|
||||||
|
private const UInt32 INFINITE = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region WaitAll and WaitAny
|
||||||
|
|
||||||
|
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles)
|
||||||
|
{
|
||||||
|
IntPtr[] nativeHandles = new IntPtr[waitHandles.Length];
|
||||||
|
for (int i = 0; i < waitHandles.Length; i++)
|
||||||
|
{
|
||||||
|
nativeHandles[i] = waitHandles[i].Handle;
|
||||||
|
}
|
||||||
|
return nativeHandles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
|
||||||
|
|
||||||
|
IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);
|
||||||
|
|
||||||
|
int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, true, timeout);
|
||||||
|
|
||||||
|
if (result == WAIT_TIMEOUT || result == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
|
||||||
|
|
||||||
|
IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);
|
||||||
|
|
||||||
|
int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, false, timeout);
|
||||||
|
|
||||||
|
if (result >= 0 && result < waitHandles.Length)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int WaitAny(WaitHandle[] waitHandles)
|
||||||
|
{
|
||||||
|
return WaitAny(waitHandles, Timeout.Infinite, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int WaitAny(WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext)
|
||||||
|
{
|
||||||
|
int millisecondsTimeout = (int)timeout.TotalMilliseconds;
|
||||||
|
|
||||||
|
return WaitAny(waitHandles, millisecondsTimeout, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region External methods
|
||||||
|
|
||||||
|
[DllImport("coredll.dll", SetLastError = true)]
|
||||||
|
public static extern int WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool fWaitAll, uint dwMilliseconds);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,82 @@
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
#if (_WINDOWS_CE)
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// EventWaitHandleFactory class.
|
||||||
|
/// This is a static class that creates AutoResetEvent and ManualResetEvent objects.
|
||||||
|
/// In WindowCE the WaitForMultipleObjects API fails to use the Handle property
|
||||||
|
/// of XxxResetEvent. It can use only handles that were created by the CreateEvent API.
|
||||||
|
/// Consequently this class creates the needed XxxResetEvent and replaces the handle if
|
||||||
|
/// it's a WindowsCE OS.
|
||||||
|
/// </summary>
|
||||||
|
public static class EventWaitHandleFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new AutoResetEvent object
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Return a new AutoResetEvent object</returns>
|
||||||
|
public static AutoResetEvent CreateAutoResetEvent()
|
||||||
|
{
|
||||||
|
AutoResetEvent waitHandle = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
#if (_WINDOWS_CE)
|
||||||
|
ReplaceEventHandle(waitHandle, false, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return waitHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new ManualResetEvent object
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Return a new ManualResetEvent object</returns>
|
||||||
|
public static ManualResetEvent CreateManualResetEvent(bool initialState)
|
||||||
|
{
|
||||||
|
ManualResetEvent waitHandle = new ManualResetEvent(initialState);
|
||||||
|
|
||||||
|
#if (_WINDOWS_CE)
|
||||||
|
ReplaceEventHandle(waitHandle, true, initialState);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return waitHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (_WINDOWS_CE)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replace the event handle
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="waitHandle">The WaitHandle object which its handle needs to be replaced.</param>
|
||||||
|
/// <param name="manualReset">Indicates if the event is a ManualResetEvent (true) or an AutoResetEvent (false)</param>
|
||||||
|
/// <param name="initialState">The initial state of the event</param>
|
||||||
|
private static void ReplaceEventHandle(WaitHandle waitHandle, bool manualReset, bool initialState)
|
||||||
|
{
|
||||||
|
// Store the old handle
|
||||||
|
IntPtr oldHandle = waitHandle.Handle;
|
||||||
|
|
||||||
|
// Create a new event
|
||||||
|
IntPtr newHandle = CreateEvent(IntPtr.Zero, manualReset, initialState, null);
|
||||||
|
|
||||||
|
// Replace the old event with the new event
|
||||||
|
waitHandle.Handle = newHandle;
|
||||||
|
|
||||||
|
// Close the old event
|
||||||
|
CloseHandle (oldHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("coredll.dll", SetLastError = true)]
|
||||||
|
public static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
|
||||||
|
|
||||||
|
//Handle
|
||||||
|
[DllImport("coredll.dll", SetLastError = true)]
|
||||||
|
public static extern bool CloseHandle(IntPtr hObject);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,81 +1,111 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
#if !(_WINDOWS_CE)
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System;
|
#endif
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
namespace Amib.Threading
|
||||||
namespace Amib.Threading
|
{
|
||||||
{
|
#region Exceptions
|
||||||
#region Exceptions
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||||
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
/// </summary>
|
||||||
/// </summary>
|
public sealed partial class WorkItemCancelException : Exception
|
||||||
[Serializable]
|
{
|
||||||
public sealed class WorkItemCancelException : ApplicationException
|
public WorkItemCancelException()
|
||||||
{
|
{
|
||||||
public WorkItemCancelException() : base()
|
}
|
||||||
{
|
|
||||||
}
|
public WorkItemCancelException(string message)
|
||||||
|
: base(message)
|
||||||
public WorkItemCancelException(string message) : base(message)
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
public WorkItemCancelException(string message, Exception e)
|
||||||
public WorkItemCancelException(string message, Exception e) : base(message, e)
|
: base(message, e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public WorkItemCancelException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
|
||||||
{
|
/// <summary>
|
||||||
}
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
}
|
/// </summary>
|
||||||
|
public sealed partial class WorkItemTimeoutException : Exception
|
||||||
/// <summary>
|
{
|
||||||
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
public WorkItemTimeoutException()
|
||||||
/// </summary>
|
{
|
||||||
[Serializable]
|
}
|
||||||
public sealed class WorkItemTimeoutException : ApplicationException
|
|
||||||
{
|
public WorkItemTimeoutException(string message)
|
||||||
public WorkItemTimeoutException() : base()
|
: base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkItemTimeoutException(string message) : base(message)
|
public WorkItemTimeoutException(string message, Exception e)
|
||||||
{
|
: base(message, e)
|
||||||
}
|
{
|
||||||
|
}
|
||||||
public WorkItemTimeoutException(string message, Exception e) : base(message, e)
|
}
|
||||||
{
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
/// </summary>
|
||||||
{
|
public sealed partial class WorkItemResultException : Exception
|
||||||
}
|
{
|
||||||
}
|
public WorkItemResultException()
|
||||||
|
{
|
||||||
/// <summary>
|
}
|
||||||
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
|
||||||
/// </summary>
|
public WorkItemResultException(string message)
|
||||||
[Serializable]
|
: base(message)
|
||||||
public sealed class WorkItemResultException : ApplicationException
|
{
|
||||||
{
|
}
|
||||||
public WorkItemResultException() : base()
|
|
||||||
{
|
public WorkItemResultException(string message, Exception e)
|
||||||
}
|
: base(message, e)
|
||||||
|
{
|
||||||
public WorkItemResultException(string message) : base(message)
|
}
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemResultException(string message, Exception e) : base(message, e)
|
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
{
|
/// <summary>
|
||||||
}
|
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||||
|
/// </summary>
|
||||||
public WorkItemResultException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
[Serializable]
|
||||||
{
|
public sealed partial class WorkItemCancelException
|
||||||
}
|
{
|
||||||
}
|
public WorkItemCancelException(SerializationInfo si, StreamingContext sc)
|
||||||
|
: base(si, sc)
|
||||||
#endregion
|
{
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public sealed partial class WorkItemTimeoutException
|
||||||
|
{
|
||||||
|
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc)
|
||||||
|
: base(si, sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public sealed partial class WorkItemResultException
|
||||||
|
{
|
||||||
|
public WorkItemResultException(SerializationInfo si, StreamingContext sc)
|
||||||
|
: base(si, sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
|
@ -1,271 +1,628 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
using System.Threading;
|
||||||
|
|
||||||
using System;
|
namespace Amib.Threading
|
||||||
using System.Threading;
|
{
|
||||||
|
#region Delegates
|
||||||
namespace Amib.Threading
|
|
||||||
{
|
/// <summary>
|
||||||
#region Delegates
|
/// A delegate that represents the method to run as the work item
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="state">A state object for the method to run</param>
|
||||||
/// A delegate that represents the method to run as the work item
|
public delegate object WorkItemCallback(object state);
|
||||||
/// </summary>
|
|
||||||
/// <param name="state">A state object for the method to run</param>
|
/// <summary>
|
||||||
public delegate object WorkItemCallback(object state);
|
/// A delegate to call after the WorkItemCallback completed
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="wir">The work item result object</param>
|
||||||
/// A delegate to call after the WorkItemCallback completed
|
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
|
||||||
/// </summary>
|
|
||||||
/// <param name="wir">The work item result object</param>
|
/// <summary>
|
||||||
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
|
/// A delegate to call after the WorkItemCallback completed
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="wir">The work item result object</param>
|
||||||
/// A delegate to call when a WorkItemsGroup becomes idle
|
public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir);
|
||||||
/// </summary>
|
|
||||||
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
|
/// <summary>
|
||||||
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
|
/// A delegate to call when a WorkItemsGroup becomes idle
|
||||||
|
/// </summary>
|
||||||
#endregion
|
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
|
||||||
|
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
|
||||||
#region WorkItem Priority
|
|
||||||
|
/// <summary>
|
||||||
public enum WorkItemPriority
|
/// A delegate to call after a thread is created, but before
|
||||||
{
|
/// it's first use.
|
||||||
Lowest,
|
/// </summary>
|
||||||
BelowNormal,
|
public delegate void ThreadInitializationHandler();
|
||||||
Normal,
|
|
||||||
AboveNormal,
|
/// <summary>
|
||||||
Highest,
|
/// A delegate to call when a thread is about to exit, after
|
||||||
}
|
/// it is no longer belong to the pool.
|
||||||
|
/// </summary>
|
||||||
#endregion
|
public delegate void ThreadTerminationHandler();
|
||||||
|
|
||||||
#region IHasWorkItemPriority interface
|
#endregion
|
||||||
|
|
||||||
public interface IHasWorkItemPriority
|
#region WorkItem Priority
|
||||||
{
|
|
||||||
WorkItemPriority WorkItemPriority { get; }
|
/// <summary>
|
||||||
}
|
/// Defines the availeable priorities of a work item.
|
||||||
|
/// The higher the priority a work item has, the sooner
|
||||||
#endregion
|
/// it will be executed.
|
||||||
|
/// </summary>
|
||||||
#region IWorkItemsGroup interface
|
public enum WorkItemPriority
|
||||||
|
{
|
||||||
/// <summary>
|
Lowest,
|
||||||
/// IWorkItemsGroup interface
|
BelowNormal,
|
||||||
/// </summary>
|
Normal,
|
||||||
public interface IWorkItemsGroup
|
AboveNormal,
|
||||||
{
|
Highest,
|
||||||
/// <summary>
|
}
|
||||||
/// Get/Set the name of the WorkItemsGroup
|
|
||||||
/// </summary>
|
#endregion
|
||||||
string Name { get; set; }
|
|
||||||
|
#region IWorkItemsGroup interface
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
/// <summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
/// IWorkItemsGroup interface
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
/// Created by SmartThreadPool.CreateWorkItemsGroup()
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
/// </summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
public interface IWorkItemsGroup
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
{
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
/// <summary>
|
||||||
|
/// Get/Set the name of the WorkItemsGroup
|
||||||
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
/// </summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
string Name { get; set; }
|
||||||
|
|
||||||
void WaitForIdle();
|
/// <summary>
|
||||||
bool WaitForIdle(TimeSpan timeout);
|
/// Get/Set the maximum number of workitem that execute cocurrency on the thread pool
|
||||||
bool WaitForIdle(int millisecondsTimeout);
|
/// </summary>
|
||||||
|
int Concurrency { get; set; }
|
||||||
int WaitingCallbacks { get; }
|
|
||||||
event WorkItemsGroupIdleHandler OnIdle;
|
/// <summary>
|
||||||
|
/// Get the number of work items waiting in the queue.
|
||||||
void Cancel();
|
/// </summary>
|
||||||
void Start();
|
int WaitingCallbacks { get; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
#endregion
|
/// Get an array with all the state objects of the currently running items.
|
||||||
|
/// The array represents a snap shot and impact performance.
|
||||||
#region CallToPostExecute enumerator
|
/// </summary>
|
||||||
|
object[] GetStates();
|
||||||
[Flags]
|
|
||||||
public enum CallToPostExecute
|
/// <summary>
|
||||||
{
|
/// Get the WorkItemsGroup start information
|
||||||
Never = 0x00,
|
/// </summary>
|
||||||
WhenWorkItemCanceled = 0x01,
|
WIGStartInfo WIGStartInfo { get; }
|
||||||
WhenWorkItemNotCanceled = 0x02,
|
|
||||||
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
|
/// <summary>
|
||||||
}
|
/// Starts to execute work items
|
||||||
|
/// </summary>
|
||||||
#endregion
|
void Start();
|
||||||
|
|
||||||
#region IWorkItemResult interface
|
/// <summary>
|
||||||
|
/// Cancel all the work items.
|
||||||
/// <summary>
|
/// Same as Cancel(false)
|
||||||
/// IWorkItemResult interface
|
/// </summary>
|
||||||
/// </summary>
|
void Cancel();
|
||||||
public interface IWorkItemResult
|
|
||||||
{
|
/// <summary>
|
||||||
/// <summary>
|
/// Cancel all work items using thread abortion
|
||||||
/// Get the result of the work item.
|
/// </summary>
|
||||||
/// If the work item didn't run yet then the caller waits.
|
/// <param name="abortExecution">True to stop work items by raising ThreadAbortException</param>
|
||||||
/// </summary>
|
void Cancel(bool abortExecution);
|
||||||
/// <returns>The result of the work item</returns>
|
|
||||||
object GetResult();
|
/// <summary>
|
||||||
|
/// Wait for all work item to complete.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Get the result of the work item.
|
void WaitForIdle();
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// Wait for all work item to complete, until timeout expired
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// </summary>
|
||||||
object GetResult(
|
/// <param name="timeout">How long to wait for the work items to complete</param>
|
||||||
int millisecondsTimeout,
|
/// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
|
||||||
bool exitContext);
|
bool WaitForIdle(TimeSpan timeout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// Wait for all work item to complete, until timeout expired
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
/// </summary>
|
||||||
/// </summary>
|
/// <param name="millisecondsTimeout">How long to wait for the work items to complete in milliseconds</param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
bool WaitForIdle(int millisecondsTimeout);
|
||||||
object GetResult(
|
|
||||||
TimeSpan timeout,
|
/// <summary>
|
||||||
bool exitContext);
|
/// IsIdle is true when there are no work items running or queued.
|
||||||
|
/// </summary>
|
||||||
void Abort();
|
bool IsIdle { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// This event is fired when all work items are completed.
|
||||||
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
/// (When IsIdle changes to true)
|
||||||
/// </summary>
|
/// This event only work on WorkItemsGroup. On SmartThreadPool
|
||||||
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
/// it throws the NotImplementedException.
|
||||||
/// <param name="exitContext">
|
/// </summary>
|
||||||
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
event WorkItemsGroupIdleHandler OnIdle;
|
||||||
/// </param>
|
|
||||||
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
#region QueueWorkItem
|
||||||
/// <returns>The result of the work item</returns>
|
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// <summary>
|
||||||
/// On cancel throws WorkItemCancelException
|
/// Queue a work item
|
||||||
object GetResult(
|
/// </summary>
|
||||||
int millisecondsTimeout,
|
/// <param name="callback">A callback to execute</param>
|
||||||
bool exitContext,
|
/// <returns>Returns a work item result</returns>
|
||||||
WaitHandle cancelWaitHandle);
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// Queue a work item
|
||||||
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
/// </summary>
|
||||||
/// </summary>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <param name="workItemPriority">The priority of the work item</param>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// <returns>Returns a work item result</returns>
|
||||||
/// On cancel throws WorkItemCancelException
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
object GetResult(
|
|
||||||
TimeSpan timeout,
|
/// <summary>
|
||||||
bool exitContext,
|
/// Queue a work item
|
||||||
WaitHandle cancelWaitHandle);
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <summary>
|
/// <param name="state">
|
||||||
/// Get the result of the work item.
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// If the work item didn't run yet then the caller waits.
|
/// </param>
|
||||||
/// </summary>
|
/// <returns>Returns a work item result</returns>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
/// <returns>The result of the work item</returns>
|
|
||||||
object GetResult(out Exception e);
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Get the result of the work item.
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
/// <param name="state">
|
||||||
/// </summary>
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
/// </param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// <returns>Returns a work item result</returns>
|
||||||
object GetResult(
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
int millisecondsTimeout,
|
|
||||||
bool exitContext,
|
/// <summary>
|
||||||
out Exception e);
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// Get the result of the work item.
|
/// <param name="state">
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// </summary>
|
/// </param>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
/// <returns>The result of the work item</returns>
|
/// A delegate to call after the callback completion
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// </param>
|
||||||
object GetResult(
|
/// <returns>Returns a work item result</returns>
|
||||||
TimeSpan timeout,
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
bool exitContext,
|
|
||||||
out Exception e);
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Get the result of the work item.
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
/// <param name="state">
|
||||||
/// </summary>
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
/// </param>
|
||||||
/// <param name="exitContext">
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
/// A delegate to call after the callback completion
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
/// <returns>Returns a work item result</returns>
|
||||||
/// <returns>The result of the work item</returns>
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
/// On timeout throws WorkItemTimeoutException
|
|
||||||
/// On cancel throws WorkItemCancelException
|
/// <summary>
|
||||||
object GetResult(
|
/// Queue a work item
|
||||||
int millisecondsTimeout,
|
/// </summary>
|
||||||
bool exitContext,
|
/// <param name="callback">A callback to execute</param>
|
||||||
WaitHandle cancelWaitHandle,
|
/// <param name="state">
|
||||||
out Exception e);
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
/// <summary>
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
/// Get the result of the work item.
|
/// A delegate to call after the callback completion
|
||||||
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
/// </param>
|
||||||
/// </summary>
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>Returns a work item result</returns>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
/// On timeout throws WorkItemTimeoutException
|
|
||||||
/// On cancel throws WorkItemCancelException
|
/// <summary>
|
||||||
object GetResult(
|
/// Queue a work item
|
||||||
TimeSpan timeout,
|
/// </summary>
|
||||||
bool exitContext,
|
/// <param name="callback">A callback to execute</param>
|
||||||
WaitHandle cancelWaitHandle,
|
/// <param name="state">
|
||||||
out Exception e);
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
/// <summary>
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
/// Gets an indication whether the asynchronous operation has completed.
|
/// A delegate to call after the callback completion
|
||||||
/// </summary>
|
/// </param>
|
||||||
bool IsCompleted { get; }
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
/// <summary>
|
/// <returns>Returns a work item result</returns>
|
||||||
/// Gets an indication whether the asynchronous operation has been canceled.
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
/// </summary>
|
|
||||||
bool IsCanceled { get; }
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
/// </summary>
|
/// <param name="callback">A callback to execute</param>
|
||||||
object State { get; }
|
/// <returns>Returns a work item result</returns>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
/// <summary>
|
|
||||||
/// Cancel the work item if it didn't start running yet.
|
/// <summary>
|
||||||
/// </summary>
|
/// Queue a work item
|
||||||
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
|
/// </summary>
|
||||||
bool Cancel();
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <summary>
|
/// <param name="state">
|
||||||
/// Get the work item's priority
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// </summary>
|
/// </param>
|
||||||
WorkItemPriority WorkItemPriority { get; }
|
/// <returns>Returns a work item result</returns>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
/// <summary>
|
|
||||||
/// Return the result, same as GetResult()
|
#endregion
|
||||||
/// </summary>
|
|
||||||
object Result { get; }
|
#region QueueWorkItem(Action<...>)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the exception if occured otherwise returns null.
|
/// Queue a work item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
object Exception { get; }
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
}
|
IWorkItemResult QueueWorkItem(Action action);
|
||||||
|
|
||||||
#endregion
|
/// <summary>
|
||||||
}
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg, WorkItemPriority priority);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2> (Action<T1, T2> action, T1 arg1, T2 arg2, WorkItemPriority priority);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2, T3> (Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem<T1, T2, T3, T4> (Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem(Func<...>)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult<TResult> object.
|
||||||
|
/// its GetResult() returns a TResult object</returns>
|
||||||
|
IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult<TResult> object.
|
||||||
|
/// its GetResult() returns a TResult object</returns>
|
||||||
|
IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult<TResult> object.
|
||||||
|
/// its GetResult() returns a TResult object</returns>
|
||||||
|
IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult<TResult> object.
|
||||||
|
/// its GetResult() returns a TResult object</returns>
|
||||||
|
IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult<TResult> object.
|
||||||
|
/// its GetResult() returns a TResult object</returns>
|
||||||
|
IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CallToPostExecute enumerator
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum CallToPostExecute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Never call to the PostExecute call back
|
||||||
|
/// </summary>
|
||||||
|
Never = 0x00,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call to the PostExecute only when the work item is cancelled
|
||||||
|
/// </summary>
|
||||||
|
WhenWorkItemCanceled = 0x01,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call to the PostExecute only when the work item is not cancelled
|
||||||
|
/// </summary>
|
||||||
|
WhenWorkItemNotCanceled = 0x02,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Always call to the PostExecute
|
||||||
|
/// </summary>
|
||||||
|
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IWorkItemResult interface
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The common interface of IWorkItemResult and IWorkItemResult<T>
|
||||||
|
/// </summary>
|
||||||
|
public interface IWaitableResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This method intent is for internal use.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
IWorkItemResult GetWorkItemResult();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method intent is for internal use.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
IWorkItemResult<TResult> GetWorkItemResultT<TResult>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IWorkItemResult interface.
|
||||||
|
/// Created when a WorkItemCallback work item is queued.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkItemResult : IWorkItemResult<object>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IWorkItemResult<TResult> interface.
|
||||||
|
/// Created when a Func<TResult> work item is queued.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkItemResult<TResult> : IWaitableResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
TResult GetResult();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
TResult GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
TResult GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
||||||
|
/// <param name="exitContext">
|
||||||
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
TResult GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
TResult GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
TResult GetResult(out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout"></param>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
TResult GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <param name="timeout"></param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
TResult GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
||||||
|
/// <param name="exitContext">
|
||||||
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
TResult GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// <param name="cancelWaitHandle"></param>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <param name="timeout"></param>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
TResult GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an indication whether the asynchronous operation has completed.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCompleted { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an indication whether the asynchronous operation has been canceled.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCanceled { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user-defined object that contains context data
|
||||||
|
/// for the work item method.
|
||||||
|
/// </summary>
|
||||||
|
object State { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as Cancel(false).
|
||||||
|
/// </summary>
|
||||||
|
bool Cancel();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel the work item execution.
|
||||||
|
/// If the work item is in the queue then it won't execute
|
||||||
|
/// If the work item is completed, it will remain completed
|
||||||
|
/// If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled
|
||||||
|
/// property to check if the work item has been cancelled. If the abortExecution is set to true then
|
||||||
|
/// the Smart Thread Pool will send an AbortException to the running thread to stop the execution
|
||||||
|
/// of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException.
|
||||||
|
/// If the work item is already cancelled it will remain cancelled
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abortExecution">When true send an AbortException to the executing thread.</param>
|
||||||
|
/// <returns>Returns true if the work item was not completed, otherwise false.</returns>
|
||||||
|
bool Cancel(bool abortExecution);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the work item's priority
|
||||||
|
/// </summary>
|
||||||
|
WorkItemPriority WorkItemPriority { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the result, same as GetResult()
|
||||||
|
/// </summary>
|
||||||
|
TResult Result { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the exception if occured otherwise returns null.
|
||||||
|
/// </summary>
|
||||||
|
object Exception { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region .NET 3.5
|
||||||
|
|
||||||
|
// All these delegate are built-in .NET 3.5
|
||||||
|
// Comment/Remove them when compiling to .NET 3.5 to avoid ambiguity.
|
||||||
|
|
||||||
|
public delegate void Action();
|
||||||
|
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
|
||||||
|
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
|
||||||
|
public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
|
||||||
|
|
||||||
|
public delegate TResult Func<TResult>();
|
||||||
|
public delegate TResult Func<T, TResult>(T arg1);
|
||||||
|
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
|
||||||
|
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
|
||||||
|
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,240 +1,239 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Collections;
|
|
||||||
using System.Diagnostics;
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
namespace Amib.Threading.Internal
|
#region PriorityQueue class
|
||||||
{
|
|
||||||
#region PriorityQueue class
|
/// <summary>
|
||||||
|
/// PriorityQueue class
|
||||||
/// <summary>
|
/// This class is not thread safe because we use external lock
|
||||||
/// PriorityQueue class
|
/// </summary>
|
||||||
/// This class is not thread safe because we use external lock
|
public sealed class PriorityQueue : IEnumerable
|
||||||
/// </summary>
|
{
|
||||||
public sealed class PriorityQueue : IEnumerable
|
#region Private members
|
||||||
{
|
|
||||||
#region Private members
|
/// <summary>
|
||||||
|
/// The number of queues, there is one for each type of priority
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The number of queues, there is one for each type of priority
|
private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
|
||||||
/// </summary>
|
|
||||||
private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
|
/// <summary>
|
||||||
|
/// Work items queues. There is one for each type of priority
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Work items queues. There is one for each type of priority
|
private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount];
|
||||||
/// </summary>
|
|
||||||
private Queue [] _queues = new Queue[_queuesCount];
|
/// <summary>
|
||||||
|
/// The total number of work items within the queues
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The total number of work items within the queues
|
private int _workItemsCount;
|
||||||
/// </summary>
|
|
||||||
private int _workItemsCount = 0;
|
/// <summary>
|
||||||
|
/// Use with IEnumerable interface
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Use with IEnumerable interface
|
private int _version;
|
||||||
/// </summary>
|
|
||||||
private int _version = 0;
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#region Contructor
|
||||||
|
|
||||||
#region Contructor
|
public PriorityQueue()
|
||||||
|
{
|
||||||
public PriorityQueue()
|
for(int i = 0; i < _queues.Length; ++i)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < _queues.Length; ++i)
|
_queues[i] = new LinkedList<IHasWorkItemPriority>();
|
||||||
{
|
}
|
||||||
_queues[i] = new Queue();
|
}
|
||||||
}
|
|
||||||
}
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#region Methods
|
||||||
|
|
||||||
#region Methods
|
/// <summary>
|
||||||
|
/// Enqueue a work item.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Enqueue a work item.
|
/// <param name="workItem">A work item</param>
|
||||||
/// </summary>
|
public void Enqueue(IHasWorkItemPriority workItem)
|
||||||
/// <param name="workItem">A work item</param>
|
{
|
||||||
public void Enqueue(IHasWorkItemPriority workItem)
|
Debug.Assert(null != workItem);
|
||||||
{
|
|
||||||
Debug.Assert(null != workItem);
|
int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
|
||||||
|
Debug.Assert(queueIndex >= 0);
|
||||||
int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
|
Debug.Assert(queueIndex < _queuesCount);
|
||||||
Debug.Assert(queueIndex >= 0);
|
|
||||||
Debug.Assert(queueIndex < _queuesCount);
|
_queues[queueIndex].AddLast(workItem);
|
||||||
|
++_workItemsCount;
|
||||||
_queues[queueIndex].Enqueue(workItem);
|
++_version;
|
||||||
++_workItemsCount;
|
}
|
||||||
++_version;
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Dequeque a work item.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Dequeque a work item.
|
/// <returns>Returns the next work item</returns>
|
||||||
/// </summary>
|
public IHasWorkItemPriority Dequeue()
|
||||||
/// <returns>Returns the next work item</returns>
|
{
|
||||||
public IHasWorkItemPriority Dequeue()
|
IHasWorkItemPriority workItem = null;
|
||||||
{
|
|
||||||
IHasWorkItemPriority workItem = null;
|
if(_workItemsCount > 0)
|
||||||
|
{
|
||||||
if(_workItemsCount > 0)
|
int queueIndex = GetNextNonEmptyQueue(-1);
|
||||||
{
|
Debug.Assert(queueIndex >= 0);
|
||||||
int queueIndex = GetNextNonEmptyQueue(-1);
|
workItem = _queues[queueIndex].First.Value;
|
||||||
Debug.Assert(queueIndex >= 0);
|
_queues[queueIndex].RemoveFirst();
|
||||||
workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority;
|
Debug.Assert(null != workItem);
|
||||||
Debug.Assert(null != workItem);
|
--_workItemsCount;
|
||||||
--_workItemsCount;
|
++_version;
|
||||||
++_version;
|
}
|
||||||
}
|
|
||||||
|
return workItem;
|
||||||
return workItem;
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Find the next non empty queue starting at queue queueIndex+1
|
||||||
/// Find the next non empty queue starting at queue queueIndex+1
|
/// </summary>
|
||||||
/// </summary>
|
/// <param name="queueIndex">The index-1 to start from</param>
|
||||||
/// <param name="queueIndex">The index-1 to start from</param>
|
/// <returns>
|
||||||
/// <returns>
|
/// The index of the next non empty queue or -1 if all the queues are empty
|
||||||
/// The index of the next non empty queue or -1 if all the queues are empty
|
/// </returns>
|
||||||
/// </returns>
|
private int GetNextNonEmptyQueue(int queueIndex)
|
||||||
private int GetNextNonEmptyQueue(int queueIndex)
|
{
|
||||||
{
|
for(int i = queueIndex+1; i < _queuesCount; ++i)
|
||||||
for(int i = queueIndex+1; i < _queuesCount; ++i)
|
{
|
||||||
{
|
if(_queues[i].Count > 0)
|
||||||
if(_queues[i].Count > 0)
|
{
|
||||||
{
|
return i;
|
||||||
return i;
|
}
|
||||||
}
|
}
|
||||||
}
|
return -1;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// The number of work items
|
||||||
/// The number of work items
|
/// </summary>
|
||||||
/// </summary>
|
public int Count
|
||||||
public int Count
|
{
|
||||||
{
|
get
|
||||||
get
|
{
|
||||||
{
|
return _workItemsCount;
|
||||||
return _workItemsCount;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Clear all the work items
|
||||||
/// Clear all the work items
|
/// </summary>
|
||||||
/// </summary>
|
public void Clear()
|
||||||
public void Clear()
|
{
|
||||||
{
|
if (_workItemsCount > 0)
|
||||||
if (_workItemsCount > 0)
|
{
|
||||||
{
|
foreach(LinkedList<IHasWorkItemPriority> queue in _queues)
|
||||||
foreach(Queue queue in _queues)
|
{
|
||||||
{
|
queue.Clear();
|
||||||
queue.Clear();
|
}
|
||||||
}
|
_workItemsCount = 0;
|
||||||
_workItemsCount = 0;
|
++_version;
|
||||||
++_version;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
#endregion
|
|
||||||
|
#region IEnumerable Members
|
||||||
#region IEnumerable Members
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Returns an enumerator to iterate over the work items
|
||||||
/// Returns an enumerator to iterate over the work items
|
/// </summary>
|
||||||
/// </summary>
|
/// <returns>Returns an enumerator</returns>
|
||||||
/// <returns>Returns an enumerator</returns>
|
public IEnumerator GetEnumerator()
|
||||||
public IEnumerator GetEnumerator()
|
{
|
||||||
{
|
return new PriorityQueueEnumerator(this);
|
||||||
return new PriorityQueueEnumerator(this);
|
}
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
#endregion
|
|
||||||
|
#region PriorityQueueEnumerator
|
||||||
#region PriorityQueueEnumerator
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// The class the implements the enumerator
|
||||||
/// The class the implements the enumerator
|
/// </summary>
|
||||||
/// </summary>
|
private class PriorityQueueEnumerator : IEnumerator
|
||||||
private class PriorityQueueEnumerator : IEnumerator
|
{
|
||||||
{
|
private readonly PriorityQueue _priorityQueue;
|
||||||
private PriorityQueue _priorityQueue;
|
private int _version;
|
||||||
private int _version;
|
private int _queueIndex;
|
||||||
private int _queueIndex;
|
private IEnumerator _enumerator;
|
||||||
private IEnumerator _enumerator;
|
|
||||||
|
public PriorityQueueEnumerator(PriorityQueue priorityQueue)
|
||||||
public PriorityQueueEnumerator(PriorityQueue priorityQueue)
|
{
|
||||||
{
|
_priorityQueue = priorityQueue;
|
||||||
_priorityQueue = priorityQueue;
|
_version = _priorityQueue._version;
|
||||||
_version = _priorityQueue._version;
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
||||||
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
if (_queueIndex >= 0)
|
||||||
if (_queueIndex >= 0)
|
{
|
||||||
{
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
_enumerator = null;
|
||||||
_enumerator = null;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#region IEnumerator Members
|
||||||
#region IEnumerator Members
|
|
||||||
|
public void Reset()
|
||||||
public void Reset()
|
{
|
||||||
{
|
_version = _priorityQueue._version;
|
||||||
_version = _priorityQueue._version;
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
||||||
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
if (_queueIndex >= 0)
|
||||||
if (_queueIndex >= 0)
|
{
|
||||||
{
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
_enumerator = null;
|
||||||
_enumerator = null;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public object Current
|
||||||
public object Current
|
{
|
||||||
{
|
get
|
||||||
get
|
{
|
||||||
{
|
Debug.Assert(null != _enumerator);
|
||||||
Debug.Assert(null != _enumerator);
|
return _enumerator.Current;
|
||||||
return _enumerator.Current;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public bool MoveNext()
|
||||||
public bool MoveNext()
|
{
|
||||||
{
|
if (null == _enumerator)
|
||||||
if (null == _enumerator)
|
{
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
if(_version != _priorityQueue._version)
|
||||||
if(_version != _priorityQueue._version)
|
{
|
||||||
{
|
throw new InvalidOperationException("The collection has been modified");
|
||||||
throw new InvalidOperationException("The collection has been modified");
|
|
||||||
|
}
|
||||||
}
|
if (!_enumerator.MoveNext())
|
||||||
if (!_enumerator.MoveNext())
|
{
|
||||||
{
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
|
||||||
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
|
if(-1 == _queueIndex)
|
||||||
if(-1 == _queueIndex)
|
{
|
||||||
{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
_enumerator.MoveNext();
|
||||||
_enumerator.MoveNext();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
#endregion
|
}
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
#endregion
|
}
|
||||||
}
|
|
||||||
|
#endregion
|
||||||
#endregion
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("Amib.Threading")]
|
||||||
|
[assembly: AssemblyDescription("Smart Thread Pool")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Amib.Threading")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: Guid("c764a3de-c4f8-434d-85b5-a09830d1e44f")]
|
||||||
|
[assembly: AssemblyVersion("2.2.3.0")]
|
||||||
|
|
||||||
|
#if (_PUBLISH)
|
||||||
|
[assembly: InternalsVisibleTo("STPTests,PublicKey=00240000048000009400000006020000002400005253413100040000010001004fe3d39add741ba7c8d52cd1eb0d94c7d79060ad956cbaff0e51c1dce94db10356b261778bc1ac3114b3218434da6fcd8416dd5507653809598f7d2afc422099ce4f6b7b0477f18e6c57c727ef2a7ab6ee56e6b4589fe44cb0e25f2875a3c65ab0383ee33c4dd93023f7ce1218bebc8b7a9a1dac878938f5c4f45ea74b6bd8ad")]
|
||||||
|
#else
|
||||||
|
[assembly: InternalsVisibleTo("STPTests")]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#if _SILVERLIGHT
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
public enum ThreadPriority
|
||||||
|
{
|
||||||
|
Lowest,
|
||||||
|
BelowNormal,
|
||||||
|
Normal,
|
||||||
|
AboveNormal,
|
||||||
|
Highest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,62 @@
|
||||||
|
#if !(_WINDOWS_CE)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#if _WINDOWS || WINDOWS_PHONE
|
||||||
|
internal static class STPEventWaitHandle
|
||||||
|
{
|
||||||
|
public const int WaitTimeout = Timeout.Infinite;
|
||||||
|
|
||||||
|
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int WaitAny(WaitHandle[] waitHandles)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAny(waitHandles);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return waitHandle.WaitOne(millisecondsTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
internal static class STPEventWaitHandle
|
||||||
|
{
|
||||||
|
public const int WaitTimeout = Timeout.Infinite;
|
||||||
|
|
||||||
|
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int WaitAny(WaitHandle[] waitHandles)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAny(waitHandles);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,354 +1,448 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
namespace Amib.Threading.Internal
|
|
||||||
{
|
namespace Amib.Threading
|
||||||
internal enum STPPerformanceCounterType
|
{
|
||||||
{
|
public interface ISTPPerformanceCountersReader
|
||||||
// Fields
|
{
|
||||||
ActiveThreads = 0,
|
long InUseThreads { get; }
|
||||||
InUseThreads = 1,
|
long ActiveThreads { get; }
|
||||||
OverheadThreads = 2,
|
long WorkItemsQueued { get; }
|
||||||
OverheadThreadsPercent = 3,
|
long WorkItemsProcessed { get; }
|
||||||
OverheadThreadsPercentBase = 4,
|
}
|
||||||
|
}
|
||||||
WorkItems = 5,
|
|
||||||
WorkItemsInQueue = 6,
|
namespace Amib.Threading.Internal
|
||||||
WorkItemsProcessed = 7,
|
{
|
||||||
|
internal interface ISTPInstancePerformanceCounters : IDisposable
|
||||||
WorkItemsQueuedPerSecond = 8,
|
{
|
||||||
WorkItemsProcessedPerSecond = 9,
|
void Close();
|
||||||
|
void SampleThreads(long activeThreads, long inUseThreads);
|
||||||
AvgWorkItemWaitTime = 10,
|
void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
|
||||||
AvgWorkItemWaitTimeBase = 11,
|
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
||||||
|
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
||||||
AvgWorkItemProcessTime = 12,
|
}
|
||||||
AvgWorkItemProcessTimeBase = 13,
|
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
|
|
||||||
WorkItemsGroups = 14,
|
internal enum STPPerformanceCounterType
|
||||||
|
{
|
||||||
LastCounter = 14,
|
// Fields
|
||||||
}
|
ActiveThreads = 0,
|
||||||
|
InUseThreads = 1,
|
||||||
|
OverheadThreads = 2,
|
||||||
/// <summary>
|
OverheadThreadsPercent = 3,
|
||||||
/// Summary description for STPPerformanceCounter.
|
OverheadThreadsPercentBase = 4,
|
||||||
/// </summary>
|
|
||||||
internal class STPPerformanceCounter
|
WorkItems = 5,
|
||||||
{
|
WorkItemsInQueue = 6,
|
||||||
// Fields
|
WorkItemsProcessed = 7,
|
||||||
private PerformanceCounterType _pcType;
|
|
||||||
protected string _counterHelp;
|
WorkItemsQueuedPerSecond = 8,
|
||||||
protected string _counterName;
|
WorkItemsProcessedPerSecond = 9,
|
||||||
|
|
||||||
// Methods
|
AvgWorkItemWaitTime = 10,
|
||||||
public STPPerformanceCounter(
|
AvgWorkItemWaitTimeBase = 11,
|
||||||
string counterName,
|
|
||||||
string counterHelp,
|
AvgWorkItemProcessTime = 12,
|
||||||
PerformanceCounterType pcType)
|
AvgWorkItemProcessTimeBase = 13,
|
||||||
{
|
|
||||||
this._counterName = counterName;
|
WorkItemsGroups = 14,
|
||||||
this._counterHelp = counterHelp;
|
|
||||||
this._pcType = pcType;
|
LastCounter = 14,
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCounterToCollection(CounterCreationDataCollection counterData)
|
|
||||||
{
|
/// <summary>
|
||||||
CounterCreationData counterCreationData = new CounterCreationData(
|
/// Summary description for STPPerformanceCounter.
|
||||||
_counterName,
|
/// </summary>
|
||||||
_counterHelp,
|
internal class STPPerformanceCounter
|
||||||
_pcType);
|
{
|
||||||
|
// Fields
|
||||||
counterData.Add(counterCreationData);
|
private readonly PerformanceCounterType _pcType;
|
||||||
}
|
protected string _counterHelp;
|
||||||
|
protected string _counterName;
|
||||||
// Properties
|
|
||||||
public string Name
|
// Methods
|
||||||
{
|
public STPPerformanceCounter(
|
||||||
get
|
string counterName,
|
||||||
{
|
string counterHelp,
|
||||||
return _counterName;
|
PerformanceCounterType pcType)
|
||||||
}
|
{
|
||||||
}
|
_counterName = counterName;
|
||||||
}
|
_counterHelp = counterHelp;
|
||||||
|
_pcType = pcType;
|
||||||
internal class STPPerformanceCounters
|
}
|
||||||
{
|
|
||||||
// Fields
|
public void AddCounterToCollection(CounterCreationDataCollection counterData)
|
||||||
internal STPPerformanceCounter[] _stpPerformanceCounters;
|
{
|
||||||
private static STPPerformanceCounters _instance;
|
CounterCreationData counterCreationData = new CounterCreationData(
|
||||||
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
|
_counterName,
|
||||||
internal const string _stpCategoryName = "SmartThreadPool";
|
_counterHelp,
|
||||||
|
_pcType);
|
||||||
// Methods
|
|
||||||
static STPPerformanceCounters()
|
counterData.Add(counterCreationData);
|
||||||
{
|
}
|
||||||
_instance = new STPPerformanceCounters();
|
|
||||||
}
|
// Properties
|
||||||
|
public string Name
|
||||||
private STPPerformanceCounters()
|
{
|
||||||
{
|
get
|
||||||
STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
|
{
|
||||||
{
|
return _counterName;
|
||||||
new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
|
}
|
||||||
new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
|
}
|
||||||
new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
|
}
|
||||||
new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
|
|
||||||
new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
|
internal class STPPerformanceCounters
|
||||||
|
{
|
||||||
new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
|
// Fields
|
||||||
new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
|
internal STPPerformanceCounter[] _stpPerformanceCounters;
|
||||||
new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
|
private static readonly STPPerformanceCounters _instance;
|
||||||
|
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
|
||||||
new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
internal const string _stpCategoryName = "SmartThreadPool";
|
||||||
new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
|
||||||
|
// Methods
|
||||||
new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64),
|
static STPPerformanceCounters()
|
||||||
new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase),
|
{
|
||||||
|
_instance = new STPPerformanceCounters();
|
||||||
new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
|
}
|
||||||
new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
|
|
||||||
|
private STPPerformanceCounters()
|
||||||
new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
|
{
|
||||||
};
|
STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
|
||||||
|
{
|
||||||
_stpPerformanceCounters = stpPerformanceCounters;
|
new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
|
||||||
SetupCategory();
|
new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
|
||||||
}
|
new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
|
||||||
private void SetupCategory()
|
new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
|
||||||
{
|
|
||||||
if (!PerformanceCounterCategory.Exists(_stpCategoryName))
|
new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
|
||||||
{
|
new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
|
||||||
CounterCreationDataCollection counters = new CounterCreationDataCollection();
|
new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
|
||||||
|
|
||||||
for (int i = 0; i < _stpPerformanceCounters.Length; i++)
|
new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
||||||
{
|
new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
||||||
_stpPerformanceCounters[i].AddCounterToCollection(counters);
|
|
||||||
}
|
new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64),
|
||||||
|
new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase),
|
||||||
|
|
||||||
// *********** Remark for .NET 2.0 ***********
|
new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
|
||||||
// If you are here, it means you got the warning that this overload
|
new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
|
||||||
// of the method is deprecated in .NET 2.0. To use the correct
|
|
||||||
// method overload, uncomment the third argument of
|
new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
|
||||||
// the method.
|
};
|
||||||
#pragma warning disable 0618
|
|
||||||
PerformanceCounterCategory.Create(
|
_stpPerformanceCounters = stpPerformanceCounters;
|
||||||
_stpCategoryName,
|
SetupCategory();
|
||||||
_stpCategoryHelp,
|
}
|
||||||
//PerformanceCounterCategoryType.MultiInstance,
|
|
||||||
counters);
|
private void SetupCategory()
|
||||||
#pragma warning restore 0618
|
{
|
||||||
}
|
if (!PerformanceCounterCategory.Exists(_stpCategoryName))
|
||||||
}
|
{
|
||||||
|
CounterCreationDataCollection counters = new CounterCreationDataCollection();
|
||||||
// Properties
|
|
||||||
public static STPPerformanceCounters Instance
|
for (int i = 0; i < _stpPerformanceCounters.Length; i++)
|
||||||
{
|
{
|
||||||
get
|
_stpPerformanceCounters[i].AddCounterToCollection(counters);
|
||||||
{
|
}
|
||||||
return _instance;
|
|
||||||
}
|
PerformanceCounterCategory.Create(
|
||||||
}
|
_stpCategoryName,
|
||||||
}
|
_stpCategoryHelp,
|
||||||
|
PerformanceCounterCategoryType.MultiInstance,
|
||||||
internal class STPInstancePerformanceCounter : IDisposable
|
counters);
|
||||||
{
|
|
||||||
// Fields
|
}
|
||||||
private PerformanceCounter _pcs;
|
}
|
||||||
|
|
||||||
// Methods
|
// Properties
|
||||||
protected STPInstancePerformanceCounter()
|
public static STPPerformanceCounters Instance
|
||||||
{
|
{
|
||||||
}
|
get
|
||||||
|
{
|
||||||
public STPInstancePerformanceCounter(
|
return _instance;
|
||||||
string instance,
|
}
|
||||||
STPPerformanceCounterType spcType)
|
}
|
||||||
{
|
}
|
||||||
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
|
||||||
_pcs = new PerformanceCounter(
|
internal class STPInstancePerformanceCounter : IDisposable
|
||||||
STPPerformanceCounters._stpCategoryName,
|
{
|
||||||
counters._stpPerformanceCounters[(int) spcType].Name,
|
// Fields
|
||||||
instance,
|
private bool _isDisposed;
|
||||||
false);
|
private PerformanceCounter _pcs;
|
||||||
_pcs.RawValue = _pcs.RawValue;
|
|
||||||
}
|
// Methods
|
||||||
|
protected STPInstancePerformanceCounter()
|
||||||
~STPInstancePerformanceCounter()
|
{
|
||||||
{
|
_isDisposed = false;
|
||||||
Close();
|
}
|
||||||
}
|
|
||||||
|
public STPInstancePerformanceCounter(
|
||||||
public void Close()
|
string instance,
|
||||||
{
|
STPPerformanceCounterType spcType) : this()
|
||||||
if (_pcs != null)
|
{
|
||||||
{
|
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
||||||
_pcs.RemoveInstance();
|
_pcs = new PerformanceCounter(
|
||||||
_pcs.Close();
|
STPPerformanceCounters._stpCategoryName,
|
||||||
_pcs = null;
|
counters._stpPerformanceCounters[(int) spcType].Name,
|
||||||
}
|
instance,
|
||||||
}
|
false);
|
||||||
|
_pcs.RawValue = _pcs.RawValue;
|
||||||
public void Dispose()
|
}
|
||||||
{
|
|
||||||
Close();
|
|
||||||
GC.SuppressFinalize(this);
|
public void Close()
|
||||||
}
|
{
|
||||||
|
if (_pcs != null)
|
||||||
public virtual void Increment()
|
{
|
||||||
{
|
_pcs.RemoveInstance();
|
||||||
_pcs.Increment();
|
_pcs.Close();
|
||||||
}
|
_pcs = null;
|
||||||
|
}
|
||||||
public virtual void IncrementBy(long val)
|
}
|
||||||
{
|
|
||||||
_pcs.IncrementBy(val);
|
public void Dispose()
|
||||||
}
|
{
|
||||||
|
Dispose(true);
|
||||||
public virtual void Set(long val)
|
}
|
||||||
{
|
|
||||||
_pcs.RawValue = val;
|
public virtual void Dispose(bool disposing)
|
||||||
}
|
{
|
||||||
}
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
|
if (disposing)
|
||||||
{
|
{
|
||||||
// Methods
|
Close();
|
||||||
public STPInstanceNullPerformanceCounter() {}
|
}
|
||||||
public override void Increment() {}
|
}
|
||||||
public override void IncrementBy(long value) {}
|
_isDisposed = true;
|
||||||
public override void Set(long val) {}
|
}
|
||||||
}
|
|
||||||
|
public virtual void Increment()
|
||||||
internal interface ISTPInstancePerformanceCounters : IDisposable
|
{
|
||||||
{
|
_pcs.Increment();
|
||||||
void Close();
|
}
|
||||||
void SampleThreads(long activeThreads, long inUseThreads);
|
|
||||||
void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
|
public virtual void IncrementBy(long val)
|
||||||
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
{
|
||||||
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
_pcs.IncrementBy(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Set(long val)
|
||||||
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
{
|
||||||
{
|
_pcs.RawValue = val;
|
||||||
// Fields
|
}
|
||||||
private STPInstancePerformanceCounter[] _pcs;
|
}
|
||||||
private static STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
|
|
||||||
|
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
|
||||||
// Methods
|
{
|
||||||
static STPInstancePerformanceCounters()
|
// Methods
|
||||||
{
|
public override void Increment() {}
|
||||||
_stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
|
public override void IncrementBy(long value) {}
|
||||||
}
|
public override void Set(long val) {}
|
||||||
|
}
|
||||||
public STPInstancePerformanceCounters(string instance)
|
|
||||||
{
|
|
||||||
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
|
|
||||||
// STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters
|
||||||
for (int i = 0; i < _pcs.Length; i++)
|
{
|
||||||
{
|
private bool _isDisposed;
|
||||||
if (instance != null)
|
// Fields
|
||||||
{
|
private STPInstancePerformanceCounter[] _pcs;
|
||||||
_pcs[i] = new STPInstancePerformanceCounter(
|
private static readonly STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
|
||||||
instance,
|
|
||||||
(STPPerformanceCounterType) i);
|
// Methods
|
||||||
}
|
static STPInstancePerformanceCounters()
|
||||||
else
|
{
|
||||||
{
|
_stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
|
||||||
_pcs[i] = _stpInstanceNullPerformanceCounter;
|
}
|
||||||
}
|
|
||||||
}
|
public STPInstancePerformanceCounters(string instance)
|
||||||
}
|
{
|
||||||
|
_isDisposed = false;
|
||||||
|
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
|
||||||
public void Close()
|
|
||||||
{
|
// Call the STPPerformanceCounters.Instance so the static constructor will
|
||||||
if (null != _pcs)
|
// intialize the STPPerformanceCounters singleton.
|
||||||
{
|
STPPerformanceCounters.Instance.GetHashCode();
|
||||||
for (int i = 0; i < _pcs.Length; i++)
|
|
||||||
{
|
for (int i = 0; i < _pcs.Length; i++)
|
||||||
if (null != _pcs[i])
|
{
|
||||||
{
|
if (instance != null)
|
||||||
_pcs[i].Close();
|
{
|
||||||
}
|
_pcs[i] = new STPInstancePerformanceCounter(
|
||||||
}
|
instance,
|
||||||
_pcs = null;
|
(STPPerformanceCounterType) i);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
~STPInstancePerformanceCounters()
|
_pcs[i] = _stpInstanceNullPerformanceCounter;
|
||||||
{
|
}
|
||||||
Close();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
public void Close()
|
||||||
Close();
|
{
|
||||||
GC.SuppressFinalize(this);
|
if (null != _pcs)
|
||||||
}
|
{
|
||||||
|
for (int i = 0; i < _pcs.Length; i++)
|
||||||
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
|
{
|
||||||
{
|
if (null != _pcs[i])
|
||||||
return _pcs[(int) spcType];
|
{
|
||||||
}
|
_pcs[i].Dispose();
|
||||||
|
}
|
||||||
public void SampleThreads(long activeThreads, long inUseThreads)
|
}
|
||||||
{
|
_pcs = null;
|
||||||
GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
|
}
|
||||||
GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
|
}
|
||||||
GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
|
|
||||||
|
public void Dispose()
|
||||||
GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
|
{
|
||||||
GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
|
public virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
|
if (!_isDisposed)
|
||||||
GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
|
{
|
||||||
GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
|
if (disposing)
|
||||||
|
{
|
||||||
GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
|
Close();
|
||||||
GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
|
}
|
||||||
}
|
}
|
||||||
|
_isDisposed = true;
|
||||||
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
|
}
|
||||||
{
|
|
||||||
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
|
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
|
||||||
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
|
{
|
||||||
}
|
return _pcs[(int) spcType];
|
||||||
|
}
|
||||||
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
|
|
||||||
{
|
public void SampleThreads(long activeThreads, long inUseThreads)
|
||||||
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
|
{
|
||||||
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
|
GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
|
||||||
}
|
GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
|
||||||
}
|
GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
|
||||||
|
|
||||||
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
|
||||||
{
|
GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
|
||||||
static NullSTPInstancePerformanceCounters()
|
}
|
||||||
{
|
|
||||||
}
|
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
|
||||||
|
{
|
||||||
private static NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(null);
|
GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
|
||||||
public static NullSTPInstancePerformanceCounters Instance
|
GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
|
||||||
{
|
|
||||||
get { return _instance; }
|
GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
|
||||||
}
|
GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
|
||||||
|
}
|
||||||
public NullSTPInstancePerformanceCounters(string instance) {}
|
|
||||||
public void Close() {}
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
|
||||||
public void Dispose() {}
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
|
||||||
public void SampleThreads(long activeThreads, long inUseThreads) {}
|
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
|
||||||
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
|
}
|
||||||
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
|
||||||
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
|
||||||
}
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
|
||||||
}
|
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
|
||||||
|
{
|
||||||
|
private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters();
|
||||||
|
|
||||||
|
public static NullSTPInstancePerformanceCounters Instance
|
||||||
|
{
|
||||||
|
get { return _instance; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close() {}
|
||||||
|
public void Dispose() {}
|
||||||
|
|
||||||
|
public void SampleThreads(long activeThreads, long inUseThreads) {}
|
||||||
|
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
|
||||||
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
||||||
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
||||||
|
public long InUseThreads
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ActiveThreads
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long WorkItemsQueued
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long WorkItemsProcessed
|
||||||
|
{
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class LocalSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
|
||||||
|
{
|
||||||
|
public void Close() { }
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
private long _activeThreads;
|
||||||
|
private long _inUseThreads;
|
||||||
|
private long _workItemsQueued;
|
||||||
|
private long _workItemsProcessed;
|
||||||
|
|
||||||
|
public long InUseThreads
|
||||||
|
{
|
||||||
|
get { return _inUseThreads; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ActiveThreads
|
||||||
|
{
|
||||||
|
get { return _activeThreads; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long WorkItemsQueued
|
||||||
|
{
|
||||||
|
get { return _workItemsQueued; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long WorkItemsProcessed
|
||||||
|
{
|
||||||
|
get { return _workItemsProcessed; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleThreads(long activeThreads, long inUseThreads)
|
||||||
|
{
|
||||||
|
_activeThreads = activeThreads;
|
||||||
|
_inUseThreads = inUseThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
|
||||||
|
{
|
||||||
|
_workItemsQueued = workItemsQueued;
|
||||||
|
_workItemsProcessed = workItemsProcessed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
|
||||||
|
{
|
||||||
|
// Not supported
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
|
||||||
|
{
|
||||||
|
// Not supported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,113 +1,212 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
using System.Threading;
|
||||||
|
|
||||||
using System.Threading;
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
namespace Amib.Threading
|
/// <summary>
|
||||||
{
|
/// Summary description for STPStartInfo.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Summary description for STPStartInfo.
|
public class STPStartInfo : WIGStartInfo
|
||||||
/// </summary>
|
{
|
||||||
public class STPStartInfo : WIGStartInfo
|
private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
||||||
{
|
private int _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
||||||
/// <summary>
|
private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
||||||
/// Idle timeout in milliseconds.
|
#if !(WINDOWS_PHONE)
|
||||||
/// If a thread is idle for _idleTimeout milliseconds then
|
private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority;
|
||||||
/// it may quit.
|
#endif
|
||||||
/// </summary>
|
private string _performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
||||||
private int _idleTimeout;
|
private bool _areThreadsBackground = SmartThreadPool.DefaultAreThreadsBackground;
|
||||||
|
private bool _enableLocalPerformanceCounters;
|
||||||
/// <summary>
|
private string _threadPoolName = SmartThreadPool.DefaultThreadPoolName;
|
||||||
/// The lower limit of threads in the pool.
|
private int? _maxStackSize = SmartThreadPool.DefaultMaxStackSize;
|
||||||
/// </summary>
|
|
||||||
private int _minWorkerThreads;
|
public STPStartInfo()
|
||||||
|
{
|
||||||
/// <summary>
|
_performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
||||||
/// The upper limit of threads in the pool.
|
#if !(WINDOWS_PHONE)
|
||||||
/// </summary>
|
_threadPriority = SmartThreadPool.DefaultThreadPriority;
|
||||||
private int _maxWorkerThreads;
|
#endif
|
||||||
|
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
||||||
/// <summary>
|
_idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
||||||
/// The priority of the threads in the pool
|
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
||||||
/// </summary>
|
}
|
||||||
private ThreadPriority _threadPriority;
|
|
||||||
|
public STPStartInfo(STPStartInfo stpStartInfo)
|
||||||
/// <summary>
|
: base(stpStartInfo)
|
||||||
/// The thread pool name. Threads will get names depending on this.
|
{
|
||||||
/// </summary>
|
_idleTimeout = stpStartInfo.IdleTimeout;
|
||||||
private string _threadPoolName;
|
_minWorkerThreads = stpStartInfo.MinWorkerThreads;
|
||||||
|
_maxWorkerThreads = stpStartInfo.MaxWorkerThreads;
|
||||||
/// <summary>
|
#if !(WINDOWS_PHONE)
|
||||||
/// If this field is not null then the performance counters are enabled
|
_threadPriority = stpStartInfo.ThreadPriority;
|
||||||
/// and use the string as the name of the instance.
|
#endif
|
||||||
/// </summary>
|
_performanceCounterInstanceName = stpStartInfo.PerformanceCounterInstanceName;
|
||||||
private string _pcInstanceName;
|
_enableLocalPerformanceCounters = stpStartInfo._enableLocalPerformanceCounters;
|
||||||
|
_threadPoolName = stpStartInfo._threadPoolName;
|
||||||
private int _stackSize;
|
_areThreadsBackground = stpStartInfo.AreThreadsBackground;
|
||||||
|
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
public STPStartInfo() : base()
|
_apartmentState = stpStartInfo._apartmentState;
|
||||||
{
|
#endif
|
||||||
_idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
}
|
||||||
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
|
||||||
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
/// <summary>
|
||||||
_threadPriority = SmartThreadPool.DefaultThreadPriority;
|
/// Get/Set the idle timeout in milliseconds.
|
||||||
_threadPoolName = SmartThreadPool.DefaultThreadPoolName;
|
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
|
||||||
_pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
/// </summary>
|
||||||
_stackSize = SmartThreadPool.DefaultStackSize;
|
public virtual int IdleTimeout
|
||||||
}
|
{
|
||||||
|
get { return _idleTimeout; }
|
||||||
public STPStartInfo(STPStartInfo stpStartInfo) : base(stpStartInfo)
|
set
|
||||||
{
|
{
|
||||||
_idleTimeout = stpStartInfo._idleTimeout;
|
ThrowIfReadOnly();
|
||||||
_minWorkerThreads = stpStartInfo._minWorkerThreads;
|
_idleTimeout = value;
|
||||||
_maxWorkerThreads = stpStartInfo._maxWorkerThreads;
|
}
|
||||||
_threadPriority = stpStartInfo._threadPriority;
|
}
|
||||||
_threadPoolName = stpStartInfo._threadPoolName;
|
|
||||||
_pcInstanceName = stpStartInfo._pcInstanceName;
|
|
||||||
_stackSize = stpStartInfo._stackSize;
|
/// <summary>
|
||||||
}
|
/// Get/Set the lower limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
public int IdleTimeout
|
public virtual int MinWorkerThreads
|
||||||
{
|
{
|
||||||
get { return _idleTimeout; }
|
get { return _minWorkerThreads; }
|
||||||
set { _idleTimeout = value; }
|
set
|
||||||
}
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
public int MinWorkerThreads
|
_minWorkerThreads = value;
|
||||||
{
|
}
|
||||||
get { return _minWorkerThreads; }
|
}
|
||||||
set { _minWorkerThreads = value; }
|
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
public int MaxWorkerThreads
|
/// Get/Set the upper limit of threads in the pool.
|
||||||
{
|
/// </summary>
|
||||||
get { return _maxWorkerThreads; }
|
public virtual int MaxWorkerThreads
|
||||||
set { _maxWorkerThreads = value; }
|
{
|
||||||
}
|
get { return _maxWorkerThreads; }
|
||||||
|
set
|
||||||
public ThreadPriority ThreadPriority
|
{
|
||||||
{
|
ThrowIfReadOnly();
|
||||||
get { return _threadPriority; }
|
_maxWorkerThreads = value;
|
||||||
set { _threadPriority = value; }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual string ThreadPoolName
|
#if !(WINDOWS_PHONE)
|
||||||
{
|
/// <summary>
|
||||||
get { return _threadPoolName; }
|
/// Get/Set the scheduling priority of the threads in the pool.
|
||||||
set { _threadPoolName = value; }
|
/// The Os handles the scheduling.
|
||||||
}
|
/// </summary>
|
||||||
|
public virtual ThreadPriority ThreadPriority
|
||||||
|
{
|
||||||
public string PerformanceCounterInstanceName
|
get { return _threadPriority; }
|
||||||
{
|
set
|
||||||
get { return _pcInstanceName; }
|
{
|
||||||
set { _pcInstanceName = value; }
|
ThrowIfReadOnly();
|
||||||
}
|
_threadPriority = value;
|
||||||
|
}
|
||||||
public int StackSize
|
}
|
||||||
{
|
#endif
|
||||||
get { return _stackSize; }
|
/// <summary>
|
||||||
set { _stackSize = value; }
|
/// Get/Set the thread pool name. Threads will get names depending on this.
|
||||||
}
|
/// </summary>
|
||||||
}
|
public virtual string ThreadPoolName {
|
||||||
}
|
get { return _threadPoolName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly ();
|
||||||
|
_threadPoolName = 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>
|
||||||
|
/// Enable/Disable the local performance counter.
|
||||||
|
/// This enables the user to get some performance information about the SmartThreadPool
|
||||||
|
/// without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.)
|
||||||
|
/// The default is false.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool EnableLocalPerformanceCounters
|
||||||
|
{
|
||||||
|
get { return _enableLocalPerformanceCounters; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
|
_enableLocalPerformanceCounters = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set backgroundness of thread in thread pool.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool AreThreadsBackground
|
||||||
|
{
|
||||||
|
get { return _areThreadsBackground; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly ();
|
||||||
|
_areThreadsBackground = 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 STPStartInfo(this) { _readOnly = true };
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
|
|
||||||
|
private ApartmentState _apartmentState = SmartThreadPool.DefaultApartmentState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the apartment state of threads in the thread pool
|
||||||
|
/// </summary>
|
||||||
|
public ApartmentState ApartmentState
|
||||||
|
{
|
||||||
|
get { return _apartmentState; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
|
_apartmentState = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the max stack size of threads in the thread pool
|
||||||
|
/// </summary>
|
||||||
|
public int? MaxStackSize
|
||||||
|
{
|
||||||
|
get { return _maxStackSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
|
if (value.HasValue && value.Value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("value", "Value must be greater than 0.");
|
||||||
|
}
|
||||||
|
_maxStackSize = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
internal class SynchronizedDictionary<TKey, TValue>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<TKey, TValue> _dictionary;
|
||||||
|
private readonly object _lock;
|
||||||
|
|
||||||
|
public SynchronizedDictionary()
|
||||||
|
{
|
||||||
|
_lock = new object();
|
||||||
|
_dictionary = new Dictionary<TKey, TValue>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _dictionary.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(TKey key)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _dictionary.ContainsKey(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(TKey key)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_dictionary.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SyncRoot
|
||||||
|
{
|
||||||
|
get { return _lock; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue this[TKey key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _dictionary[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_dictionary[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<TKey, TValue>.KeyCollection Keys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _dictionary.Keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<TKey, TValue>.ValueCollection Values
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _dictionary.Values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_dictionary.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,99 +1,171 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
|
||||||
|
namespace Amib.Threading
|
||||||
namespace Amib.Threading
|
{
|
||||||
{
|
/// <summary>
|
||||||
/// <summary>
|
/// Summary description for WIGStartInfo.
|
||||||
/// Summary description for WIGStartInfo.
|
/// </summary>
|
||||||
/// </summary>
|
public class WIGStartInfo
|
||||||
public class WIGStartInfo
|
{
|
||||||
{
|
private bool _useCallerCallContext;
|
||||||
/// <summary>
|
private bool _useCallerHttpContext;
|
||||||
/// Use the caller's security context
|
private bool _disposeOfStateObjects;
|
||||||
/// </summary>
|
private CallToPostExecute _callToPostExecute;
|
||||||
private bool _useCallerCallContext;
|
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
||||||
|
private bool _startSuspended;
|
||||||
/// <summary>
|
private WorkItemPriority _workItemPriority;
|
||||||
/// Use the caller's HTTP context
|
private bool _fillStateWithArgs;
|
||||||
/// </summary>
|
|
||||||
private bool _useCallerHttpContext;
|
protected bool _readOnly;
|
||||||
|
|
||||||
/// <summary>
|
public WIGStartInfo()
|
||||||
/// Dispose of the state object of a work item
|
{
|
||||||
/// </summary>
|
_fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
|
||||||
private bool _disposeOfStateObjects;
|
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
|
||||||
|
_startSuspended = SmartThreadPool.DefaultStartSuspended;
|
||||||
/// <summary>
|
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
||||||
/// The option to run the post execute
|
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
||||||
/// </summary>
|
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
||||||
private CallToPostExecute _callToPostExecute;
|
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
||||||
|
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
||||||
/// <summary>
|
}
|
||||||
/// A post execute callback to call when none is provided in
|
|
||||||
/// the QueueWorkItem method.
|
public WIGStartInfo(WIGStartInfo wigStartInfo)
|
||||||
/// </summary>
|
{
|
||||||
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
_useCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
_useCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
/// <summary>
|
_disposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
/// Indicate the WorkItemsGroup to suspend the handling of the work items
|
_callToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
/// until the Start() method is called.
|
_postExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
/// </summary>
|
_workItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
private bool _startSuspended;
|
_startSuspended = wigStartInfo.StartSuspended;
|
||||||
|
_fillStateWithArgs = wigStartInfo.FillStateWithArgs;
|
||||||
public WIGStartInfo()
|
}
|
||||||
{
|
|
||||||
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
protected void ThrowIfReadOnly()
|
||||||
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
{
|
||||||
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
if (_readOnly)
|
||||||
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
{
|
||||||
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
throw new NotSupportedException("This is a readonly instance and set is not supported");
|
||||||
_startSuspended = SmartThreadPool.DefaultStartSuspended;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WIGStartInfo(WIGStartInfo wigStartInfo)
|
/// <summary>
|
||||||
{
|
/// Get/Set if to use the caller's security context
|
||||||
_useCallerCallContext = wigStartInfo._useCallerCallContext;
|
/// </summary>
|
||||||
_useCallerHttpContext = wigStartInfo._useCallerHttpContext;
|
public virtual bool UseCallerCallContext
|
||||||
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
|
{
|
||||||
_callToPostExecute = wigStartInfo._callToPostExecute;
|
get { return _useCallerCallContext; }
|
||||||
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
|
set
|
||||||
_startSuspended = wigStartInfo._startSuspended;
|
{
|
||||||
}
|
ThrowIfReadOnly();
|
||||||
|
_useCallerCallContext = value;
|
||||||
public bool UseCallerCallContext
|
}
|
||||||
{
|
}
|
||||||
get { return _useCallerCallContext; }
|
|
||||||
set { _useCallerCallContext = value; }
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's HTTP context
|
||||||
public bool UseCallerHttpContext
|
/// </summary>
|
||||||
{
|
public virtual bool UseCallerHttpContext
|
||||||
get { return _useCallerHttpContext; }
|
{
|
||||||
set { _useCallerHttpContext = value; }
|
get { return _useCallerHttpContext; }
|
||||||
}
|
set
|
||||||
|
{
|
||||||
public bool DisposeOfStateObjects
|
ThrowIfReadOnly();
|
||||||
{
|
_useCallerHttpContext = value;
|
||||||
get { return _disposeOfStateObjects; }
|
}
|
||||||
set { _disposeOfStateObjects = value; }
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public CallToPostExecute CallToPostExecute
|
/// <summary>
|
||||||
{
|
/// Get/Set if to dispose of the state object of a work item
|
||||||
get { return _callToPostExecute; }
|
/// </summary>
|
||||||
set { _callToPostExecute = value; }
|
public virtual bool DisposeOfStateObjects
|
||||||
}
|
{
|
||||||
|
get { return _disposeOfStateObjects; }
|
||||||
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
set
|
||||||
{
|
{
|
||||||
get { return _postExecuteWorkItemCallback; }
|
ThrowIfReadOnly();
|
||||||
set { _postExecuteWorkItemCallback = value; }
|
_disposeOfStateObjects = value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public bool StartSuspended
|
|
||||||
{
|
|
||||||
get { return _startSuspended; }
|
/// <summary>
|
||||||
set { _startSuspended = value; }
|
/// 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 WIGStartInfo(this) { _readOnly = true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,333 +1,343 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
using System;
|
{
|
||||||
|
#region WorkItemFactory class
|
||||||
namespace Amib.Threading.Internal
|
|
||||||
{
|
public class WorkItemFactory
|
||||||
#region WorkItemFactory class
|
{
|
||||||
|
/// <summary>
|
||||||
public class WorkItemFactory
|
/// Create a new work item
|
||||||
{
|
/// </summary>
|
||||||
/// <summary>
|
/// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
|
||||||
/// Create a new work item
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// </summary>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <returns>Returns a work item</returns>
|
||||||
/// <param name="callback">A callback to execute</param>
|
public static WorkItem CreateWorkItem(
|
||||||
/// <returns>Returns a work item</returns>
|
IWorkItemsGroup workItemsGroup,
|
||||||
public static WorkItem CreateWorkItem(
|
WIGStartInfo wigStartInfo,
|
||||||
IWorkItemsGroup workItemsGroup,
|
WorkItemCallback callback)
|
||||||
WIGStartInfo wigStartInfo,
|
{
|
||||||
WorkItemCallback callback)
|
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
|
||||||
{
|
}
|
||||||
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Create a new work item
|
/// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
|
||||||
/// </summary>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="workItemPriority">The priority of the work item</param>
|
||||||
/// <param name="workItemPriority">The priority of the work item</param>
|
/// <returns>Returns a work item</returns>
|
||||||
/// <returns>Returns a work item</returns>
|
public static WorkItem CreateWorkItem(
|
||||||
public static WorkItem CreateWorkItem(
|
IWorkItemsGroup workItemsGroup,
|
||||||
IWorkItemsGroup workItemsGroup,
|
WIGStartInfo wigStartInfo,
|
||||||
WIGStartInfo wigStartInfo,
|
WorkItemCallback callback,
|
||||||
WorkItemCallback callback,
|
WorkItemPriority workItemPriority)
|
||||||
WorkItemPriority workItemPriority)
|
{
|
||||||
{
|
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
|
||||||
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
|
}
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// Create a new work item
|
||||||
/// Create a new work item
|
/// </summary>
|
||||||
/// </summary>
|
/// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="workItemInfo">Work item info</param>
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
public static WorkItem CreateWorkItem(
|
public static WorkItem CreateWorkItem(
|
||||||
IWorkItemsGroup workItemsGroup,
|
IWorkItemsGroup workItemsGroup,
|
||||||
WIGStartInfo wigStartInfo,
|
WIGStartInfo wigStartInfo,
|
||||||
WorkItemInfo workItemInfo,
|
WorkItemInfo workItemInfo,
|
||||||
WorkItemCallback callback)
|
WorkItemCallback callback)
|
||||||
{
|
{
|
||||||
return CreateWorkItem(
|
return CreateWorkItem(
|
||||||
workItemsGroup,
|
workItemsGroup,
|
||||||
wigStartInfo,
|
wigStartInfo,
|
||||||
workItemInfo,
|
workItemInfo,
|
||||||
callback,
|
callback,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="state">
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// <param name="state">
|
||||||
/// </param>
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// <returns>Returns a work item</returns>
|
/// </param>
|
||||||
public static WorkItem CreateWorkItem(
|
/// <returns>Returns a work item</returns>
|
||||||
IWorkItemsGroup workItemsGroup,
|
public static WorkItem CreateWorkItem(
|
||||||
WIGStartInfo wigStartInfo,
|
IWorkItemsGroup workItemsGroup,
|
||||||
WorkItemCallback callback,
|
WIGStartInfo wigStartInfo,
|
||||||
object state)
|
WorkItemCallback callback,
|
||||||
{
|
object state)
|
||||||
ValidateCallback(callback);
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
WorkItem workItem = new WorkItem(
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
WorkItem workItem = new WorkItem(
|
||||||
callback,
|
workItemsGroup,
|
||||||
state);
|
workItemInfo,
|
||||||
return workItem;
|
callback,
|
||||||
}
|
state);
|
||||||
|
return workItem;
|
||||||
/// <summary>
|
}
|
||||||
/// Create a new work item
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// Create a new work item
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// </summary>
|
||||||
/// <param name="state">
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// </param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
/// <param name="state">
|
||||||
/// <returns>Returns a work item</returns>
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
public static WorkItem CreateWorkItem(
|
/// </param>
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
WIGStartInfo wigStartInfo,
|
/// <returns>Returns a work item</returns>
|
||||||
WorkItemCallback callback,
|
public static WorkItem CreateWorkItem(
|
||||||
object state,
|
IWorkItemsGroup workItemsGroup,
|
||||||
WorkItemPriority workItemPriority)
|
WIGStartInfo wigStartInfo,
|
||||||
{
|
WorkItemCallback callback,
|
||||||
ValidateCallback(callback);
|
object state,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
{
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
ValidateCallback(callback);
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
|
||||||
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
workItemInfo.WorkItemPriority = workItemPriority;
|
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
WorkItem workItem = new WorkItem(
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
workItemsGroup,
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
workItemInfo,
|
|
||||||
callback,
|
WorkItem workItem = new WorkItem(
|
||||||
state);
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
return workItem;
|
callback,
|
||||||
}
|
state);
|
||||||
|
|
||||||
/// <summary>
|
return workItem;
|
||||||
/// Create a new work item
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <summary>
|
||||||
/// <param name="workItemInfo">Work item information</param>
|
/// Create a new work item
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// </summary>
|
||||||
/// <param name="state">
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// </param>
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <param name="callback">A callback to execute</param>
|
||||||
public static WorkItem CreateWorkItem(
|
/// <param name="state">
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
WIGStartInfo wigStartInfo,
|
/// </param>
|
||||||
WorkItemInfo workItemInfo,
|
/// <returns>Returns a work item</returns>
|
||||||
WorkItemCallback callback,
|
public static WorkItem CreateWorkItem(
|
||||||
object state)
|
IWorkItemsGroup workItemsGroup,
|
||||||
{
|
WIGStartInfo wigStartInfo,
|
||||||
ValidateCallback(callback);
|
WorkItemInfo workItemInfo,
|
||||||
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
WorkItemCallback callback,
|
||||||
|
object state)
|
||||||
WorkItem workItem = new WorkItem(
|
{
|
||||||
workItemsGroup,
|
ValidateCallback(callback);
|
||||||
new WorkItemInfo(workItemInfo),
|
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
||||||
callback,
|
|
||||||
state);
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
return workItem;
|
new WorkItemInfo(workItemInfo),
|
||||||
}
|
callback,
|
||||||
|
state);
|
||||||
/// <summary>
|
|
||||||
/// Create a new work item
|
return workItem;
|
||||||
/// </summary>
|
}
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <summary>
|
||||||
/// <param name="state">
|
/// Create a new work item
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// </summary>
|
||||||
/// </param>
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// A delegate to call after the callback completion
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// </param>
|
/// <param name="state">
|
||||||
/// <returns>Returns a work item</returns>
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
public static WorkItem CreateWorkItem(
|
/// </param>
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
WIGStartInfo wigStartInfo,
|
/// A delegate to call after the callback completion
|
||||||
WorkItemCallback callback,
|
/// </param>
|
||||||
object state,
|
/// <returns>Returns a work item</returns>
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
public static WorkItem CreateWorkItem(
|
||||||
{
|
IWorkItemsGroup workItemsGroup,
|
||||||
ValidateCallback(callback);
|
WIGStartInfo wigStartInfo,
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
{
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
ValidateCallback(callback);
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
WorkItem workItem = new WorkItem(
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
workItemsGroup,
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
workItemInfo,
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
callback,
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
state);
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
|
|
||||||
return workItem;
|
WorkItem workItem = new WorkItem(
|
||||||
}
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
/// <summary>
|
callback,
|
||||||
/// Create a new work item
|
state);
|
||||||
/// </summary>
|
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
return workItem;
|
||||||
/// <param name="callback">A callback to execute</param>
|
}
|
||||||
/// <param name="state">
|
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// <summary>
|
||||||
/// </param>
|
/// Create a new work item
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
/// </summary>
|
||||||
/// A delegate to call after the callback completion
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// </param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <param name="state">
|
||||||
public static WorkItem CreateWorkItem(
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// </param>
|
||||||
WIGStartInfo wigStartInfo,
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
WorkItemCallback callback,
|
/// A delegate to call after the callback completion
|
||||||
object state,
|
/// </param>
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
WorkItemPriority workItemPriority)
|
/// <returns>Returns a work item</returns>
|
||||||
{
|
public static WorkItem CreateWorkItem(
|
||||||
ValidateCallback(callback);
|
IWorkItemsGroup workItemsGroup,
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
object state,
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
WorkItemPriority workItemPriority)
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
{
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
ValidateCallback(callback);
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
workItemInfo.WorkItemPriority = workItemPriority;
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
WorkItem workItem = new WorkItem(
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
workItemsGroup,
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
workItemInfo,
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
callback,
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
state);
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
return workItem;
|
|
||||||
}
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
/// <summary>
|
workItemInfo,
|
||||||
/// Create a new work item
|
callback,
|
||||||
/// </summary>
|
state);
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
|
||||||
/// <param name="callback">A callback to execute</param>
|
return workItem;
|
||||||
/// <param name="state">
|
}
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
|
||||||
/// </param>
|
/// <summary>
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
/// Create a new work item
|
||||||
/// A delegate to call after the callback completion
|
/// </summary>
|
||||||
/// </param>
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <param name="callback">A callback to execute</param>
|
||||||
public static WorkItem CreateWorkItem(
|
/// <param name="state">
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
WIGStartInfo wigStartInfo,
|
/// </param>
|
||||||
WorkItemCallback callback,
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
object state,
|
/// A delegate to call after the callback completion
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
/// </param>
|
||||||
CallToPostExecute callToPostExecute)
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
{
|
/// <returns>Returns a work item</returns>
|
||||||
ValidateCallback(callback);
|
public static WorkItem CreateWorkItem(
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
WorkItemCallback callback,
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
object state,
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
CallToPostExecute callToPostExecute)
|
||||||
workItemInfo.CallToPostExecute = callToPostExecute;
|
{
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
WorkItem workItem = new WorkItem(
|
|
||||||
workItemsGroup,
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
workItemInfo,
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
callback,
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
state);
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = callToPostExecute;
|
||||||
return workItem;
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
}
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
|
|
||||||
/// <summary>
|
WorkItem workItem = new WorkItem(
|
||||||
/// Create a new work item
|
workItemsGroup,
|
||||||
/// </summary>
|
workItemInfo,
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
callback,
|
||||||
/// <param name="callback">A callback to execute</param>
|
state);
|
||||||
/// <param name="state">
|
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
return workItem;
|
||||||
/// </param>
|
}
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
|
||||||
/// A delegate to call after the callback completion
|
/// <summary>
|
||||||
/// </param>
|
/// Create a new work item
|
||||||
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
/// </summary>
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
public static WorkItem CreateWorkItem(
|
/// <param name="callback">A callback to execute</param>
|
||||||
IWorkItemsGroup workItemsGroup,
|
/// <param name="state">
|
||||||
WIGStartInfo wigStartInfo,
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
WorkItemCallback callback,
|
/// </param>
|
||||||
object state,
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
/// A delegate to call after the callback completion
|
||||||
CallToPostExecute callToPostExecute,
|
/// </param>
|
||||||
WorkItemPriority workItemPriority)
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
{
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
ValidateCallback(callback);
|
public static WorkItem CreateWorkItem(
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
WorkItemCallback callback,
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
object state,
|
||||||
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
CallToPostExecute callToPostExecute,
|
||||||
workItemInfo.CallToPostExecute = callToPostExecute;
|
WorkItemPriority workItemPriority)
|
||||||
workItemInfo.WorkItemPriority = workItemPriority;
|
{
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
|
||||||
|
ValidateCallback(callback);
|
||||||
WorkItem workItem = new WorkItem(
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
callback,
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
state);
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
return workItem;
|
workItemInfo.CallToPostExecute = callToPostExecute;
|
||||||
}
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
private static void ValidateCallback(Delegate callback)
|
|
||||||
{
|
WorkItem workItem = new WorkItem(
|
||||||
if(callback.GetInvocationList().Length > 1)
|
workItemsGroup,
|
||||||
{
|
workItemInfo,
|
||||||
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
|
callback,
|
||||||
}
|
state);
|
||||||
}
|
|
||||||
}
|
return workItem;
|
||||||
|
}
|
||||||
#endregion
|
|
||||||
}
|
private static void ValidateCallback(Delegate callback)
|
||||||
|
{
|
||||||
|
if (callback != null && callback.GetInvocationList().Length > 1)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
|
@ -1,102 +1,69 @@
|
||||||
// Ami Bar
|
namespace Amib.Threading
|
||||||
// amibar@gmail.com
|
{
|
||||||
|
#region WorkItemInfo class
|
||||||
namespace Amib.Threading
|
|
||||||
{
|
/// <summary>
|
||||||
#region WorkItemInfo class
|
/// Summary description for WorkItemInfo.
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
public class WorkItemInfo
|
||||||
/// Summary description for WorkItemInfo.
|
{
|
||||||
/// </summary>
|
public WorkItemInfo()
|
||||||
public class WorkItemInfo
|
{
|
||||||
{
|
UseCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
||||||
/// <summary>
|
UseCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
||||||
/// Use the caller's security context
|
DisposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
||||||
/// </summary>
|
CallToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
||||||
private bool _useCallerCallContext;
|
PostExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
||||||
|
WorkItemPriority = SmartThreadPool.DefaultWorkItemPriority;
|
||||||
/// <summary>
|
}
|
||||||
/// Use the caller's security context
|
|
||||||
/// </summary>
|
public WorkItemInfo(WorkItemInfo workItemInfo)
|
||||||
private bool _useCallerHttpContext;
|
{
|
||||||
|
UseCallerCallContext = workItemInfo.UseCallerCallContext;
|
||||||
/// <summary>
|
UseCallerHttpContext = workItemInfo.UseCallerHttpContext;
|
||||||
/// Dispose of the state object of a work item
|
DisposeOfStateObjects = workItemInfo.DisposeOfStateObjects;
|
||||||
/// </summary>
|
CallToPostExecute = workItemInfo.CallToPostExecute;
|
||||||
private bool _disposeOfStateObjects;
|
PostExecuteWorkItemCallback = workItemInfo.PostExecuteWorkItemCallback;
|
||||||
|
WorkItemPriority = workItemInfo.WorkItemPriority;
|
||||||
/// <summary>
|
Timeout = workItemInfo.Timeout;
|
||||||
/// The option to run the post execute
|
}
|
||||||
/// </summary>
|
|
||||||
private CallToPostExecute _callToPostExecute;
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's security context
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// A post execute callback to call when none is provided in
|
public bool UseCallerCallContext { get; set; }
|
||||||
/// the QueueWorkItem method.
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
/// Get/Set if to use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
public bool UseCallerHttpContext { get; set; }
|
||||||
/// The priority of the work item
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
private WorkItemPriority _workItemPriority;
|
/// Get/Set if to dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
public WorkItemInfo()
|
public bool DisposeOfStateObjects { get; set; }
|
||||||
{
|
|
||||||
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
/// <summary>
|
||||||
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
/// Get/Set the run the post execute options
|
||||||
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
/// </summary>
|
||||||
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
public CallToPostExecute CallToPostExecute { get; set; }
|
||||||
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
|
||||||
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
|
/// <summary>
|
||||||
}
|
/// Get/Set the post execute callback
|
||||||
|
/// </summary>
|
||||||
public WorkItemInfo(WorkItemInfo workItemInfo)
|
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback { get; set; }
|
||||||
{
|
|
||||||
_useCallerCallContext = workItemInfo._useCallerCallContext;
|
/// <summary>
|
||||||
_useCallerHttpContext = workItemInfo._useCallerHttpContext;
|
/// Get/Set the work item's priority
|
||||||
_disposeOfStateObjects = workItemInfo._disposeOfStateObjects;
|
/// </summary>
|
||||||
_callToPostExecute = workItemInfo._callToPostExecute;
|
public WorkItemPriority WorkItemPriority { get; set; }
|
||||||
_postExecuteWorkItemCallback = workItemInfo._postExecuteWorkItemCallback;
|
|
||||||
_workItemPriority = workItemInfo._workItemPriority;
|
/// <summary>
|
||||||
}
|
/// Get/Set the work item's timout in milliseconds.
|
||||||
|
/// This is a passive timout. When the timout expires the work item won't be actively aborted!
|
||||||
public bool UseCallerCallContext
|
/// </summary>
|
||||||
{
|
public long Timeout { get; set; }
|
||||||
get { return _useCallerCallContext; }
|
}
|
||||||
set { _useCallerCallContext = value; }
|
|
||||||
}
|
#endregion
|
||||||
|
}
|
||||||
public bool UseCallerHttpContext
|
|
||||||
{
|
|
||||||
get { return _useCallerHttpContext; }
|
|
||||||
set { _useCallerHttpContext = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DisposeOfStateObjects
|
|
||||||
{
|
|
||||||
get { return _disposeOfStateObjects; }
|
|
||||||
set { _disposeOfStateObjects = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallToPostExecute CallToPostExecute
|
|
||||||
{
|
|
||||||
get { return _callToPostExecute; }
|
|
||||||
set { _callToPostExecute = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
|
||||||
{
|
|
||||||
get { return _postExecuteWorkItemCallback; }
|
|
||||||
set { _postExecuteWorkItemCallback = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemPriority WorkItemPriority
|
|
||||||
{
|
|
||||||
get { return _workItemPriority; }
|
|
||||||
set { _workItemPriority = value; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region WorkItemResultTWrapper class
|
||||||
|
|
||||||
|
internal class WorkItemResultTWrapper<TResult> : IWorkItemResult<TResult>, IInternalWaitableResult
|
||||||
|
{
|
||||||
|
private readonly IWorkItemResult _workItemResult;
|
||||||
|
|
||||||
|
public WorkItemResultTWrapper(IWorkItemResult workItemResult)
|
||||||
|
{
|
||||||
|
_workItemResult = workItemResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IWorkItemResult<TResult> Members
|
||||||
|
|
||||||
|
public TResult GetResult()
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(int millisecondsTimeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(TimeSpan timeout, bool exitContext)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(timeout, exitContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(timeout, exitContext, cancelWaitHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(out Exception e)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(out e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, out e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(TimeSpan timeout, bool exitContext, out Exception e)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(timeout, exitContext, out e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
|
||||||
|
{
|
||||||
|
return (TResult)_workItemResult.GetResult(timeout, exitContext, cancelWaitHandle, out e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCompleted
|
||||||
|
{
|
||||||
|
get { return _workItemResult.IsCompleted; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsCanceled
|
||||||
|
{
|
||||||
|
get { return _workItemResult.IsCanceled; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object State
|
||||||
|
{
|
||||||
|
get { return _workItemResult.State; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Cancel()
|
||||||
|
{
|
||||||
|
return _workItemResult.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Cancel(bool abortExecution)
|
||||||
|
{
|
||||||
|
return _workItemResult.Cancel(abortExecution);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemPriority WorkItemPriority
|
||||||
|
{
|
||||||
|
get { return _workItemResult.WorkItemPriority; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult Result
|
||||||
|
{
|
||||||
|
get { return (TResult)_workItemResult.Result; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Exception
|
||||||
|
{
|
||||||
|
get { return (TResult)_workItemResult.Exception; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IInternalWorkItemResult Members
|
||||||
|
|
||||||
|
public IWorkItemResult GetWorkItemResult()
|
||||||
|
{
|
||||||
|
return _workItemResult.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TRes> GetWorkItemResultT<TRes>()
|
||||||
|
{
|
||||||
|
return (IWorkItemResult<TRes>)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
|
@ -1,512 +1,361 @@
|
||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
|
||||||
using System.Runtime.CompilerServices;
|
namespace Amib.Threading.Internal
|
||||||
using System.Diagnostics;
|
{
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
#region WorkItemsGroup class
|
||||||
{
|
|
||||||
#region WorkItemsGroup class
|
/// <summary>
|
||||||
|
/// Summary description for WorkItemsGroup.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Summary description for WorkItemsGroup.
|
public class WorkItemsGroup : WorkItemsGroupBase
|
||||||
/// </summary>
|
{
|
||||||
public class WorkItemsGroup : IWorkItemsGroup
|
#region Private members
|
||||||
{
|
|
||||||
#region Private members
|
private readonly object _lock = new object();
|
||||||
|
|
||||||
private object _lock = new object();
|
/// <summary>
|
||||||
/// <summary>
|
/// A reference to the SmartThreadPool instance that created this
|
||||||
/// Contains the name of this instance of SmartThreadPool.
|
/// WorkItemsGroup.
|
||||||
/// Can be changed by the user.
|
/// </summary>
|
||||||
/// </summary>
|
private readonly SmartThreadPool _stp;
|
||||||
private string _name = "WorkItemsGroup";
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// The OnIdle event
|
||||||
/// A reference to the SmartThreadPool instance that created this
|
/// </summary>
|
||||||
/// WorkItemsGroup.
|
private event WorkItemsGroupIdleHandler _onIdle;
|
||||||
/// </summary>
|
|
||||||
private SmartThreadPool _stp;
|
/// <summary>
|
||||||
|
/// A flag to indicate if the Work Items Group is now suspended.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// The OnIdle event
|
private bool _isSuspended;
|
||||||
/// </summary>
|
|
||||||
private event WorkItemsGroupIdleHandler _onIdle;
|
/// <summary>
|
||||||
|
/// Defines how many work items of this WorkItemsGroup can run at once.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Defines how many work items of this WorkItemsGroup can run at once.
|
private int _concurrency;
|
||||||
/// </summary>
|
|
||||||
private int _concurrency;
|
/// <summary>
|
||||||
|
/// Priority queue to hold work items before they are passed
|
||||||
/// <summary>
|
/// to the SmartThreadPool.
|
||||||
/// Priority queue to hold work items before they are passed
|
/// </summary>
|
||||||
/// to the SmartThreadPool.
|
private readonly PriorityQueue _workItemsQueue;
|
||||||
/// </summary>
|
|
||||||
private PriorityQueue _workItemsQueue;
|
/// <summary>
|
||||||
|
/// Indicate how many work items are waiting in the SmartThreadPool
|
||||||
/// <summary>
|
/// queue.
|
||||||
/// Indicate how many work items are waiting in the SmartThreadPool
|
/// This value is used to apply the concurrency.
|
||||||
/// queue.
|
/// </summary>
|
||||||
/// This value is used to apply the concurrency.
|
private int _workItemsInStpQueue;
|
||||||
/// </summary>
|
|
||||||
private int _workItemsInStpQueue;
|
/// <summary>
|
||||||
|
/// Indicate how many work items are currently running in the SmartThreadPool.
|
||||||
/// <summary>
|
/// This value is used with the Cancel, to calculate if we can send new
|
||||||
/// Indicate how many work items are currently running in the SmartThreadPool.
|
/// work items to the STP.
|
||||||
/// This value is used with the Cancel, to calculate if we can send new
|
/// </summary>
|
||||||
/// work items to the STP.
|
private int _workItemsExecutingInStp = 0;
|
||||||
/// </summary>
|
|
||||||
private int _workItemsExecutingInStp = 0;
|
/// <summary>
|
||||||
|
/// WorkItemsGroup start information
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// WorkItemsGroup start information
|
private readonly WIGStartInfo _workItemsGroupStartInfo;
|
||||||
/// </summary>
|
|
||||||
private WIGStartInfo _workItemsGroupStartInfo;
|
/// <summary>
|
||||||
|
/// Signaled when all of the WorkItemsGroup's work item completed.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Signaled when all of the WorkItemsGroup's work item completed.
|
//private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
||||||
/// </summary>
|
private readonly ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true);
|
||||||
private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
|
||||||
|
/// <summary>
|
||||||
/// <summary>
|
/// A common object for all the work items that this work items group
|
||||||
/// A common object for all the work items that this work items group
|
/// generate so we can mark them to cancel in O(1)
|
||||||
/// generate so we can mark them to cancel in O(1)
|
/// </summary>
|
||||||
/// </summary>
|
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
||||||
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
|
||||||
|
#endregion
|
||||||
#endregion
|
|
||||||
|
#region Construction
|
||||||
#region Construction
|
|
||||||
|
public WorkItemsGroup(
|
||||||
public WorkItemsGroup(
|
SmartThreadPool stp,
|
||||||
SmartThreadPool stp,
|
int concurrency,
|
||||||
int concurrency,
|
WIGStartInfo wigStartInfo)
|
||||||
WIGStartInfo wigStartInfo)
|
{
|
||||||
{
|
if (concurrency <= 0)
|
||||||
if (concurrency <= 0)
|
{
|
||||||
{
|
throw new ArgumentOutOfRangeException(
|
||||||
throw new ArgumentOutOfRangeException("concurrency", concurrency, "concurrency must be greater than zero");
|
"concurrency",
|
||||||
}
|
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
|
||||||
_stp = stp;
|
concurrency,
|
||||||
_concurrency = concurrency;
|
#endif
|
||||||
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo);
|
"concurrency must be greater than zero");
|
||||||
_workItemsQueue = new PriorityQueue();
|
}
|
||||||
|
_stp = stp;
|
||||||
// The _workItemsInStpQueue gets the number of currently executing work items,
|
_concurrency = concurrency;
|
||||||
// because once a work item is executing, it cannot be cancelled.
|
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo).AsReadOnly();
|
||||||
_workItemsInStpQueue = _workItemsExecutingInStp;
|
_workItemsQueue = new PriorityQueue();
|
||||||
}
|
Name = "WorkItemsGroup";
|
||||||
|
|
||||||
#endregion
|
// The _workItemsInStpQueue gets the number of currently executing work items,
|
||||||
|
// because once a work item is executing, it cannot be cancelled.
|
||||||
#region IWorkItemsGroup implementation
|
_workItemsInStpQueue = _workItemsExecutingInStp;
|
||||||
|
|
||||||
/// <summary>
|
_isSuspended = _workItemsGroupStartInfo.StartSuspended;
|
||||||
/// Get/Set the name of the SmartThreadPool instance
|
}
|
||||||
/// </summary>
|
|
||||||
public string Name
|
#endregion
|
||||||
{
|
|
||||||
get
|
#region WorkItemsGroupBase Overrides
|
||||||
{
|
|
||||||
return _name;
|
public override int Concurrency
|
||||||
}
|
{
|
||||||
|
get { return _concurrency; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_name = value;
|
Debug.Assert(value > 0);
|
||||||
}
|
|
||||||
}
|
int diff = value - _concurrency;
|
||||||
|
_concurrency = value;
|
||||||
/// <summary>
|
if (diff > 0)
|
||||||
/// Queue a work item
|
{
|
||||||
/// </summary>
|
EnqueueToSTPNextNWorkItem(diff);
|
||||||
/// <param name="callback">A callback to execute</param>
|
}
|
||||||
/// <returns>Returns a work item result</returns>
|
}
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
|
}
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback);
|
public override int WaitingCallbacks
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
{
|
||||||
return workItem.GetWorkItemResult();
|
get { return _workItemsQueue.Count; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override object[] GetStates()
|
||||||
/// Queue a work item
|
{
|
||||||
/// </summary>
|
lock (_lock)
|
||||||
/// <param name="callback">A callback to execute</param>
|
{
|
||||||
/// <param name="workItemPriority">The priority of the work item</param>
|
object[] states = new object[_workItemsQueue.Count];
|
||||||
/// <returns>Returns a work item result</returns>
|
int i = 0;
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
|
foreach (WorkItem workItem in _workItemsQueue)
|
||||||
{
|
{
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, workItemPriority);
|
states[i] = workItem.GetWorkItemResult().State;
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
++i;
|
||||||
return workItem.GetWorkItemResult();
|
}
|
||||||
}
|
return states;
|
||||||
|
}
|
||||||
/// <summary>
|
}
|
||||||
/// Queue a work item
|
|
||||||
/// </summary>
|
/// <summary>
|
||||||
/// <param name="workItemInfo">Work item info</param>
|
/// WorkItemsGroup start information
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// </summary>
|
||||||
/// <returns>Returns a work item result</returns>
|
public override WIGStartInfo WIGStartInfo
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
|
{
|
||||||
{
|
get { return _workItemsGroupStartInfo; }
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback);
|
}
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
/// <summary>
|
||||||
}
|
/// Start the Work Items Group if it was started suspended
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
public override void Start()
|
||||||
/// Queue a work item
|
{
|
||||||
/// </summary>
|
// If the Work Items Group already started then quit
|
||||||
/// <param name="callback">A callback to execute</param>
|
if (!_isSuspended)
|
||||||
/// <param name="state">
|
{
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
return;
|
||||||
/// </param>
|
}
|
||||||
/// <returns>Returns a work item result</returns>
|
_isSuspended = false;
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
|
|
||||||
{
|
EnqueueToSTPNextNWorkItem(Math.Min(_workItemsQueue.Count, _concurrency));
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state);
|
}
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
public override void Cancel(bool abortExecution)
|
||||||
}
|
{
|
||||||
|
lock (_lock)
|
||||||
/// <summary>
|
{
|
||||||
/// Queue a work item
|
_canceledWorkItemsGroup.IsCanceled = true;
|
||||||
/// </summary>
|
_workItemsQueue.Clear();
|
||||||
/// <param name="callback">A callback to execute</param>
|
_workItemsInStpQueue = 0;
|
||||||
/// <param name="state">
|
_canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
}
|
||||||
/// </param>
|
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
if (abortExecution)
|
||||||
/// <returns>Returns a work item result</returns>
|
{
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
|
_stp.CancelAbortWorkItemsGroup(this);
|
||||||
{
|
}
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, workItemPriority);
|
}
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
/// <summary>
|
||||||
}
|
/// Wait for the thread pool to be idle
|
||||||
|
/// </summary>
|
||||||
/// <summary>
|
public override bool WaitForIdle(int millisecondsTimeout)
|
||||||
/// Queue a work item
|
{
|
||||||
/// </summary>
|
SmartThreadPool.ValidateWorkItemsGroupWaitForIdle(this);
|
||||||
/// <param name="workItemInfo">Work item information</param>
|
return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false);
|
||||||
/// <param name="callback">A callback to execute</param>
|
}
|
||||||
/// <param name="state">
|
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
public override event WorkItemsGroupIdleHandler OnIdle
|
||||||
/// </param>
|
{
|
||||||
/// <returns>Returns a work item result</returns>
|
add { _onIdle += value; }
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
|
remove { _onIdle -= value; }
|
||||||
{
|
}
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback, state);
|
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
#endregion
|
||||||
return workItem.GetWorkItemResult();
|
|
||||||
}
|
#region Private methods
|
||||||
|
|
||||||
/// <summary>
|
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
|
||||||
/// Queue a work item
|
{
|
||||||
/// </summary>
|
IInternalWorkItemResult iwir = (IInternalWorkItemResult)wir;
|
||||||
/// <param name="callback">A callback to execute</param>
|
iwir.OnWorkItemStarted += OnWorkItemStartedCallback;
|
||||||
/// <param name="state">
|
iwir.OnWorkItemCompleted += OnWorkItemCompletedCallback;
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
}
|
||||||
/// </param>
|
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
public void OnSTPIsStarting()
|
||||||
/// A delegate to call after the callback completion
|
{
|
||||||
/// </param>
|
if (_isSuspended)
|
||||||
/// <returns>Returns a work item result</returns>
|
{
|
||||||
public IWorkItemResult QueueWorkItem(
|
return;
|
||||||
WorkItemCallback callback,
|
}
|
||||||
object state,
|
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
EnqueueToSTPNextNWorkItem(_concurrency);
|
||||||
{
|
}
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback);
|
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
public void EnqueueToSTPNextNWorkItem(int count)
|
||||||
return workItem.GetWorkItemResult();
|
{
|
||||||
}
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
/// <summary>
|
EnqueueToSTPNextWorkItem(null, false);
|
||||||
/// Queue a work item
|
}
|
||||||
/// </summary>
|
}
|
||||||
/// <param name="callback">A callback to execute</param>
|
|
||||||
/// <param name="state">
|
private object FireOnIdle(object state)
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
{
|
||||||
/// </param>
|
FireOnIdleImpl(_onIdle);
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
return null;
|
||||||
/// A delegate to call after the callback completion
|
}
|
||||||
/// </param>
|
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
/// <returns>Returns a work item result</returns>
|
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
|
||||||
public IWorkItemResult QueueWorkItem(
|
{
|
||||||
WorkItemCallback callback,
|
if(null == onIdle)
|
||||||
object state,
|
{
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
return;
|
||||||
WorkItemPriority workItemPriority)
|
}
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
|
Delegate[] delegates = onIdle.GetInvocationList();
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
foreach(WorkItemsGroupIdleHandler eh in delegates)
|
||||||
return workItem.GetWorkItemResult();
|
{
|
||||||
}
|
try
|
||||||
|
{
|
||||||
/// <summary>
|
eh(this);
|
||||||
/// Queue a work item
|
}
|
||||||
/// </summary>
|
catch { } // Suppress exceptions
|
||||||
/// <param name="callback">A callback to execute</param>
|
}
|
||||||
/// <param name="state">
|
}
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
|
||||||
/// </param>
|
private void OnWorkItemStartedCallback(WorkItem workItem)
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
{
|
||||||
/// A delegate to call after the callback completion
|
lock(_lock)
|
||||||
/// </param>
|
{
|
||||||
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
++_workItemsExecutingInStp;
|
||||||
/// <returns>Returns a work item result</returns>
|
}
|
||||||
public IWorkItemResult QueueWorkItem(
|
}
|
||||||
WorkItemCallback callback,
|
|
||||||
object state,
|
private void OnWorkItemCompletedCallback(WorkItem workItem)
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
{
|
||||||
CallToPostExecute callToPostExecute)
|
EnqueueToSTPNextWorkItem(null, true);
|
||||||
{
|
}
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
|
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
internal override void Enqueue(WorkItem workItem)
|
||||||
return workItem.GetWorkItemResult();
|
{
|
||||||
}
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
}
|
||||||
/// <summary>
|
|
||||||
/// Queue a work item
|
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
|
||||||
/// </summary>
|
{
|
||||||
/// <param name="callback">A callback to execute</param>
|
EnqueueToSTPNextWorkItem(workItem, false);
|
||||||
/// <param name="state">
|
}
|
||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
|
||||||
/// </param>
|
private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
|
||||||
/// <param name="postExecuteWorkItemCallback">
|
{
|
||||||
/// A delegate to call after the callback completion
|
lock(_lock)
|
||||||
/// </param>
|
{
|
||||||
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
// Got here from OnWorkItemCompletedCallback()
|
||||||
/// <param name="workItemPriority">The work item priority</param>
|
if (decrementWorkItemsInStpQueue)
|
||||||
/// <returns>Returns a work item result</returns>
|
{
|
||||||
public IWorkItemResult QueueWorkItem(
|
--_workItemsInStpQueue;
|
||||||
WorkItemCallback callback,
|
|
||||||
object state,
|
if(_workItemsInStpQueue < 0)
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
{
|
||||||
CallToPostExecute callToPostExecute,
|
_workItemsInStpQueue = 0;
|
||||||
WorkItemPriority workItemPriority)
|
}
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
|
--_workItemsExecutingInStp;
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
if(_workItemsExecutingInStp < 0)
|
||||||
}
|
{
|
||||||
|
_workItemsExecutingInStp = 0;
|
||||||
/// <summary>
|
}
|
||||||
/// Wait for the thread pool to be idle
|
}
|
||||||
/// </summary>
|
|
||||||
public void WaitForIdle()
|
// If the work item is not null then enqueue it
|
||||||
{
|
if (null != workItem)
|
||||||
WaitForIdle(Timeout.Infinite);
|
{
|
||||||
}
|
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
|
||||||
|
|
||||||
/// <summary>
|
RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
|
||||||
/// Wait for the thread pool to be idle
|
_workItemsQueue.Enqueue(workItem);
|
||||||
/// </summary>
|
//_stp.IncrementWorkItemsCount();
|
||||||
public bool WaitForIdle(TimeSpan timeout)
|
|
||||||
{
|
if ((1 == _workItemsQueue.Count) &&
|
||||||
return WaitForIdle((int)timeout.TotalMilliseconds);
|
(0 == _workItemsInStpQueue))
|
||||||
}
|
{
|
||||||
|
_stp.RegisterWorkItemsGroup(this);
|
||||||
/// <summary>
|
IsIdle = false;
|
||||||
/// Wait for the thread pool to be idle
|
_isIdleWaitHandle.Reset();
|
||||||
/// </summary>
|
}
|
||||||
public bool WaitForIdle(int millisecondsTimeout)
|
}
|
||||||
{
|
|
||||||
_stp.ValidateWorkItemsGroupWaitForIdle(this);
|
// If the work items queue of the group is empty than quit
|
||||||
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
if (0 == _workItemsQueue.Count)
|
||||||
}
|
{
|
||||||
|
if (0 == _workItemsInStpQueue)
|
||||||
public int WaitingCallbacks
|
{
|
||||||
{
|
_stp.UnregisterWorkItemsGroup(this);
|
||||||
get
|
IsIdle = true;
|
||||||
{
|
_isIdleWaitHandle.Set();
|
||||||
return _workItemsQueue.Count;
|
if (decrementWorkItemsInStpQueue && _onIdle != null && _onIdle.GetInvocationList().Length > 0)
|
||||||
}
|
{
|
||||||
}
|
_stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
|
||||||
|
}
|
||||||
public event WorkItemsGroupIdleHandler OnIdle
|
}
|
||||||
{
|
return;
|
||||||
add
|
}
|
||||||
{
|
|
||||||
_onIdle += value;
|
if (!_isSuspended)
|
||||||
}
|
{
|
||||||
remove
|
if (_workItemsInStpQueue < _concurrency)
|
||||||
{
|
{
|
||||||
_onIdle -= value;
|
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
|
||||||
}
|
try
|
||||||
}
|
{
|
||||||
|
_stp.Enqueue(nextWorkItem);
|
||||||
public void Cancel()
|
}
|
||||||
{
|
catch (ObjectDisposedException e)
|
||||||
lock(_lock)
|
{
|
||||||
{
|
e.GetHashCode();
|
||||||
_canceledWorkItemsGroup.IsCanceled = true;
|
// The STP has been shutdown
|
||||||
_workItemsQueue.Clear();
|
}
|
||||||
_workItemsInStpQueue = 0;
|
|
||||||
_canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
++_workItemsInStpQueue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void Start()
|
}
|
||||||
{
|
|
||||||
lock (this)
|
#endregion
|
||||||
{
|
}
|
||||||
if (!_workItemsGroupStartInfo.StartSuspended)
|
|
||||||
{
|
#endregion
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
_workItemsGroupStartInfo.StartSuspended = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < _concurrency; ++i)
|
|
||||||
{
|
|
||||||
EnqueueToSTPNextWorkItem(null, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Private methods
|
|
||||||
|
|
||||||
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
|
|
||||||
{
|
|
||||||
IInternalWorkItemResult iwir = wir as IInternalWorkItemResult;
|
|
||||||
iwir.OnWorkItemStarted += new WorkItemStateCallback(OnWorkItemStartedCallback);
|
|
||||||
iwir.OnWorkItemCompleted += new WorkItemStateCallback(OnWorkItemCompletedCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSTPIsStarting()
|
|
||||||
{
|
|
||||||
lock (this)
|
|
||||||
{
|
|
||||||
if (_workItemsGroupStartInfo.StartSuspended)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < _concurrency; ++i)
|
|
||||||
{
|
|
||||||
EnqueueToSTPNextWorkItem(null, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private object FireOnIdle(object state)
|
|
||||||
{
|
|
||||||
FireOnIdleImpl(_onIdle);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
|
|
||||||
{
|
|
||||||
if(null == onIdle)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Delegate[] delegates = onIdle.GetInvocationList();
|
|
||||||
foreach(WorkItemsGroupIdleHandler eh in delegates)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
eh(this);
|
|
||||||
}
|
|
||||||
// Ignore exceptions
|
|
||||||
catch{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWorkItemStartedCallback(WorkItem workItem)
|
|
||||||
{
|
|
||||||
lock(_lock)
|
|
||||||
{
|
|
||||||
++_workItemsExecutingInStp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWorkItemCompletedCallback(WorkItem workItem)
|
|
||||||
{
|
|
||||||
EnqueueToSTPNextWorkItem(null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
|
|
||||||
{
|
|
||||||
EnqueueToSTPNextWorkItem(workItem, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
|
|
||||||
{
|
|
||||||
lock(_lock)
|
|
||||||
{
|
|
||||||
// Got here from OnWorkItemCompletedCallback()
|
|
||||||
if (decrementWorkItemsInStpQueue)
|
|
||||||
{
|
|
||||||
--_workItemsInStpQueue;
|
|
||||||
|
|
||||||
if(_workItemsInStpQueue < 0)
|
|
||||||
{
|
|
||||||
_workItemsInStpQueue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
--_workItemsExecutingInStp;
|
|
||||||
|
|
||||||
if(_workItemsExecutingInStp < 0)
|
|
||||||
{
|
|
||||||
_workItemsExecutingInStp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the work item is not null then enqueue it
|
|
||||||
if (null != workItem)
|
|
||||||
{
|
|
||||||
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
|
|
||||||
|
|
||||||
RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
|
|
||||||
_workItemsQueue.Enqueue(workItem);
|
|
||||||
//_stp.IncrementWorkItemsCount();
|
|
||||||
|
|
||||||
if ((1 == _workItemsQueue.Count) &&
|
|
||||||
(0 == _workItemsInStpQueue))
|
|
||||||
{
|
|
||||||
_stp.RegisterWorkItemsGroup(this);
|
|
||||||
Trace.WriteLine("WorkItemsGroup " + Name + " is NOT idle");
|
|
||||||
_isIdleWaitHandle.Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the work items queue of the group is empty than quit
|
|
||||||
if (0 == _workItemsQueue.Count)
|
|
||||||
{
|
|
||||||
if (0 == _workItemsInStpQueue)
|
|
||||||
{
|
|
||||||
_stp.UnregisterWorkItemsGroup(this);
|
|
||||||
Trace.WriteLine("WorkItemsGroup " + Name + " is idle");
|
|
||||||
_isIdleWaitHandle.Set();
|
|
||||||
_stp.QueueWorkItem(new WorkItemCallback(this.FireOnIdle));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_workItemsGroupStartInfo.StartSuspended)
|
|
||||||
{
|
|
||||||
if (_workItemsInStpQueue < _concurrency)
|
|
||||||
{
|
|
||||||
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
|
|
||||||
_stp.Enqueue(nextWorkItem, true);
|
|
||||||
++_workItemsInStpQueue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,471 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
public abstract class WorkItemsGroupBase : IWorkItemsGroup
|
||||||
|
{
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the name of this instance of SmartThreadPool.
|
||||||
|
/// Can be changed by the user.
|
||||||
|
/// </summary>
|
||||||
|
private string _name = "WorkItemsGroupBase";
|
||||||
|
|
||||||
|
public WorkItemsGroupBase()
|
||||||
|
{
|
||||||
|
IsIdle = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IWorkItemsGroup Members
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the name of the SmartThreadPool/WorkItemsGroup instance
|
||||||
|
/// </summary>
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return _name; }
|
||||||
|
set { _name = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Abstract Methods
|
||||||
|
|
||||||
|
public abstract int Concurrency { get; set; }
|
||||||
|
public abstract int WaitingCallbacks { get; }
|
||||||
|
public abstract object[] GetStates();
|
||||||
|
public abstract WIGStartInfo WIGStartInfo { get; }
|
||||||
|
public abstract void Start();
|
||||||
|
public abstract void Cancel(bool abortExecution);
|
||||||
|
public abstract bool WaitForIdle(int millisecondsTimeout);
|
||||||
|
public abstract event WorkItemsGroupIdleHandler OnIdle;
|
||||||
|
|
||||||
|
internal abstract void Enqueue(WorkItem workItem);
|
||||||
|
internal virtual void PreQueueWorkItem() { }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Common Base Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel all the work items.
|
||||||
|
/// Same as Cancel(false)
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Cancel()
|
||||||
|
{
|
||||||
|
Cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for the SmartThreadPool/WorkItemsGroup to be idle
|
||||||
|
/// </summary>
|
||||||
|
public void WaitForIdle()
|
||||||
|
{
|
||||||
|
WaitForIdle(Timeout.Infinite);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for the SmartThreadPool/WorkItemsGroup to be idle
|
||||||
|
/// </summary>
|
||||||
|
public bool WaitForIdle(TimeSpan timeout)
|
||||||
|
{
|
||||||
|
return WaitForIdle((int)timeout.TotalMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IsIdle is true when there are no work items running or queued.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIdle { get; protected set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="workItemPriority">The priority of the work item</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, workItemPriority);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, workItemInfo, callback);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, workItemPriority);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, workItemInfo, callback, state);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem(Action<...>)
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem(Action action)
|
||||||
|
{
|
||||||
|
return QueueWorkItem (action, SmartThreadPool.DefaultWorkItemPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem ();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem (
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke ();
|
||||||
|
return null;
|
||||||
|
}, priority);
|
||||||
|
Enqueue (workItem);
|
||||||
|
return workItem.GetWorkItemResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T>(Action<T> action, T arg)
|
||||||
|
{
|
||||||
|
return QueueWorkItem<T> (action, arg, SmartThreadPool.DefaultWorkItemPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg, WorkItemPriority priority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem ();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem (
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
action.Invoke (arg);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null, priority);
|
||||||
|
Enqueue (workItem);
|
||||||
|
return workItem.GetWorkItemResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
|
||||||
|
{
|
||||||
|
return QueueWorkItem<T1, T2> (action, arg1, arg2, SmartThreadPool.DefaultWorkItemPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2> (Action<T1, T2> action, T1 arg1, T2 arg2, WorkItemPriority priority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem ();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem (
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
action.Invoke (arg1, arg2);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null, priority);
|
||||||
|
Enqueue (workItem);
|
||||||
|
return workItem.GetWorkItemResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
|
||||||
|
{
|
||||||
|
return QueueWorkItem<T1, T2, T3> (action, arg1, arg2, arg3, SmartThreadPool.DefaultWorkItemPriority);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2, T3> (Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem ();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem (
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
action.Invoke (arg1, arg2, arg3);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null, priority);
|
||||||
|
Enqueue (workItem);
|
||||||
|
return workItem.GetWorkItemResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2, T3, T4>(
|
||||||
|
Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||||
|
{
|
||||||
|
return QueueWorkItem<T1, T2, T3, T4> (action, arg1, arg2, arg3, arg4,
|
||||||
|
SmartThreadPool.DefaultWorkItemPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2, T3, T4> (
|
||||||
|
Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem ();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem (
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
action.Invoke (arg1, arg2, arg3, arg4);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null, priority);
|
||||||
|
Enqueue (workItem);
|
||||||
|
return workItem.GetWorkItemResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem(Func<...>)
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
return func.Invoke();
|
||||||
|
});
|
||||||
|
Enqueue(workItem);
|
||||||
|
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
return func.Invoke(arg);
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
return func.Invoke(arg1, arg2);
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(
|
||||||
|
Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
return func.Invoke(arg1, arg2, arg3);
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(
|
||||||
|
Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
state =>
|
||||||
|
{
|
||||||
|
return func.Invoke(arg1, arg2, arg3, arg4);
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -21,18 +21,21 @@
|
||||||
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
||||||
; *
|
; *
|
||||||
[Startup]
|
[Startup]
|
||||||
|
; Place to create a PID file
|
||||||
|
; If no path if specified then a PID file is not created.
|
||||||
|
; PIDFile = "/tmp/my.pid"
|
||||||
|
|
||||||
; Plugin Registry Location
|
; Plugin Registry Location
|
||||||
; Set path to directory for plugin registry. Information
|
; Set path to directory for plugin registry. Information
|
||||||
; about the registered repositories and installed plugins
|
; about the registered repositories and installed plugins
|
||||||
; will be stored here
|
; will be stored here
|
||||||
; The Robust.exe process must have R/W access to the location
|
; The Robust.exe process must have R/W access to the location
|
||||||
RegistryLocation = "."
|
RegistryLocation = "."
|
||||||
|
|
||||||
; Modular configurations
|
; Modular configurations
|
||||||
; Set path to directory for modular ini files...
|
; Set path to directory for modular ini files...
|
||||||
; The Robust.exe process must have R/W access to the location
|
; The Robust.exe process must have R/W access to the location
|
||||||
ConfigDirectory = "/home/opensim/etc/Configs"
|
ConfigDirectory = "/home/opensim/etc/Configs"
|
||||||
|
|
||||||
[ServiceList]
|
[ServiceList]
|
||||||
|
|
||||||
|
|
|
@ -13,19 +13,21 @@
|
||||||
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
|
||||||
; *
|
; *
|
||||||
[Startup]
|
[Startup]
|
||||||
|
; Place to create a PID file
|
||||||
|
; If no path if specified then a PID file is not created.
|
||||||
|
; PIDFile = "/tmp/my.pid"
|
||||||
|
|
||||||
; Plugin Registry Location
|
; Plugin Registry Location
|
||||||
; Set path to directory for plugin registry. Information
|
; Set path to directory for plugin registry. Information
|
||||||
; about the registered repositories and installed plugins
|
; about the registered repositories and installed plugins
|
||||||
; will be stored here
|
; will be stored here
|
||||||
; The Robust.exe process must have R/W access to the location
|
; The Robust.exe process must have R/W access to the location
|
||||||
RegistryLocation = "."
|
RegistryLocation = "."
|
||||||
|
|
||||||
|
; Modular configurations
|
||||||
; Modular configurations
|
; Set path to directory for modular ini files...
|
||||||
; Set path to directory for modular ini files...
|
; The Robust.exe process must have R/W access to the location
|
||||||
; The Robust.exe process must have R/W access to the location
|
ConfigDirectory = "/home/opensim/etc/Configs"
|
||||||
ConfigDirectory = "/home/opensim/etc/Configs"
|
|
||||||
|
|
||||||
[ServiceList]
|
[ServiceList]
|
||||||
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
|
||||||
|
|
Loading…
Reference in New Issue