mirror of
https://github.com/farcasclaudiu/SmartThreadPool.git
synced 2026-06-28 15:01:07 +03:00
v2.0
SmartThreadPool v2.0
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
Generated
+316
@@ -0,0 +1,316 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace STPCEDemo
|
||||||
|
{
|
||||||
|
partial class Form1
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
private System.Windows.Forms.MainMenu mainMenu1;
|
||||||
|
private UsageControl.UsageHistoryControl usageHistoryControl1;
|
||||||
|
private Button btnStartStop;
|
||||||
|
private Label label1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.mainMenu1 = new System.Windows.Forms.MainMenu();
|
||||||
|
this.btnStartStop = new System.Windows.Forms.Button();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.lblThreadsInUse = new System.Windows.Forms.Label();
|
||||||
|
this.label7 = new System.Windows.Forms.Label();
|
||||||
|
this.lblThreadsInPool = new System.Windows.Forms.Label();
|
||||||
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
|
this.spnMinThreads = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
|
this.label3 = new System.Windows.Forms.Label();
|
||||||
|
this.label5 = new System.Windows.Forms.Label();
|
||||||
|
this.spnMaxThreads = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.spnIdleTimeout = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.spnWorkItemsPerSecond = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.label6 = new System.Windows.Forms.Label();
|
||||||
|
this.spnWorkItemDuration = new System.Windows.Forms.NumericUpDown();
|
||||||
|
this.label8 = new System.Windows.Forms.Label();
|
||||||
|
this.usageControl1 = new UsageControl.UsageControl();
|
||||||
|
this.usageHistoryControl1 = new UsageControl.UsageHistoryControl();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// btnStartStop
|
||||||
|
//
|
||||||
|
this.btnStartStop.Location = new System.Drawing.Point(148, 10);
|
||||||
|
this.btnStartStop.Name = "btnStartStop";
|
||||||
|
this.btnStartStop.Size = new System.Drawing.Size(72, 20);
|
||||||
|
this.btnStartStop.TabIndex = 0;
|
||||||
|
this.btnStartStop.Text = "Start";
|
||||||
|
this.btnStartStop.Click += new System.EventHandler(this.btnStartStop_Click);
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Bold);
|
||||||
|
this.label1.Location = new System.Drawing.Point(10, 10);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(143, 20);
|
||||||
|
this.label1.Text = "Smart Thread Pool";
|
||||||
|
//
|
||||||
|
// lblThreadsInUse
|
||||||
|
//
|
||||||
|
this.lblThreadsInUse.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.lblThreadsInUse.Location = new System.Drawing.Point(148, 106);
|
||||||
|
this.lblThreadsInUse.Name = "lblThreadsInUse";
|
||||||
|
this.lblThreadsInUse.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.lblThreadsInUse.Text = "0";
|
||||||
|
this.lblThreadsInUse.TextAlign = System.Drawing.ContentAlignment.TopCenter;
|
||||||
|
//
|
||||||
|
// label7
|
||||||
|
//
|
||||||
|
this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label7.Location = new System.Drawing.Point(10, 106);
|
||||||
|
this.label7.Name = "label7";
|
||||||
|
this.label7.Size = new System.Drawing.Size(124, 24);
|
||||||
|
this.label7.Text = "Used threads (Green)";
|
||||||
|
//
|
||||||
|
// lblThreadsInPool
|
||||||
|
//
|
||||||
|
this.lblThreadsInPool.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.lblThreadsInPool.Location = new System.Drawing.Point(148, 88);
|
||||||
|
this.lblThreadsInPool.Name = "lblThreadsInPool";
|
||||||
|
this.lblThreadsInPool.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.lblThreadsInPool.Text = "0";
|
||||||
|
this.lblThreadsInPool.TextAlign = System.Drawing.ContentAlignment.TopCenter;
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label2.Location = new System.Drawing.Point(10, 88);
|
||||||
|
this.label2.Name = "label2";
|
||||||
|
this.label2.Size = new System.Drawing.Size(124, 24);
|
||||||
|
this.label2.Text = "Threads in pool (Red)";
|
||||||
|
//
|
||||||
|
// spnMinThreads
|
||||||
|
//
|
||||||
|
this.spnMinThreads.Location = new System.Drawing.Point(148, 125);
|
||||||
|
this.spnMinThreads.Maximum = new decimal(new int[] {
|
||||||
|
10,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnMinThreads.Name = "spnMinThreads";
|
||||||
|
this.spnMinThreads.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.spnMinThreads.TabIndex = 3;
|
||||||
|
this.spnMinThreads.ValueChanged += new System.EventHandler(this.spnMinThreads_ValueChanged);
|
||||||
|
//
|
||||||
|
// label4
|
||||||
|
//
|
||||||
|
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label4.Location = new System.Drawing.Point(10, 173);
|
||||||
|
this.label4.Name = "label4";
|
||||||
|
this.label4.Size = new System.Drawing.Size(120, 24);
|
||||||
|
this.label4.Text = "Idle timeout (Seconds)";
|
||||||
|
//
|
||||||
|
// label3
|
||||||
|
//
|
||||||
|
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label3.Location = new System.Drawing.Point(10, 149);
|
||||||
|
this.label3.Name = "label3";
|
||||||
|
this.label3.Size = new System.Drawing.Size(104, 24);
|
||||||
|
this.label3.Text = "Maximum Threads";
|
||||||
|
//
|
||||||
|
// label5
|
||||||
|
//
|
||||||
|
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label5.Location = new System.Drawing.Point(10, 125);
|
||||||
|
this.label5.Name = "label5";
|
||||||
|
this.label5.Size = new System.Drawing.Size(104, 24);
|
||||||
|
this.label5.Text = "Minimum Threads";
|
||||||
|
//
|
||||||
|
// spnMaxThreads
|
||||||
|
//
|
||||||
|
this.spnMaxThreads.Location = new System.Drawing.Point(148, 149);
|
||||||
|
this.spnMaxThreads.Maximum = new decimal(new int[] {
|
||||||
|
10,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnMaxThreads.Minimum = new decimal(new int[] {
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnMaxThreads.Name = "spnMaxThreads";
|
||||||
|
this.spnMaxThreads.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.spnMaxThreads.TabIndex = 4;
|
||||||
|
this.spnMaxThreads.Value = new decimal(new int[] {
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnMaxThreads.ValueChanged += new System.EventHandler(this.spnMaxThreads_ValueChanged);
|
||||||
|
//
|
||||||
|
// spnIdleTimeout
|
||||||
|
//
|
||||||
|
this.spnIdleTimeout.Location = new System.Drawing.Point(148, 173);
|
||||||
|
this.spnIdleTimeout.Maximum = new decimal(new int[] {
|
||||||
|
60,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnIdleTimeout.Minimum = new decimal(new int[] {
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnIdleTimeout.Name = "spnIdleTimeout";
|
||||||
|
this.spnIdleTimeout.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.spnIdleTimeout.TabIndex = 5;
|
||||||
|
this.spnIdleTimeout.Value = new decimal(new int[] {
|
||||||
|
10,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
//
|
||||||
|
// spnWorkItemsPerSecond
|
||||||
|
//
|
||||||
|
this.spnWorkItemsPerSecond.Location = new System.Drawing.Point(148, 203);
|
||||||
|
this.spnWorkItemsPerSecond.Name = "spnWorkItemsPerSecond";
|
||||||
|
this.spnWorkItemsPerSecond.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.spnWorkItemsPerSecond.TabIndex = 6;
|
||||||
|
this.spnWorkItemsPerSecond.Value = new decimal(new int[] {
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
//
|
||||||
|
// label6
|
||||||
|
//
|
||||||
|
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label6.Location = new System.Drawing.Point(10, 203);
|
||||||
|
this.label6.Name = "label6";
|
||||||
|
this.label6.Size = new System.Drawing.Size(120, 24);
|
||||||
|
this.label6.Text = "Work items/sec";
|
||||||
|
//
|
||||||
|
// spnWorkItemDuration
|
||||||
|
//
|
||||||
|
this.spnWorkItemDuration.Increment = new decimal(new int[] {
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnWorkItemDuration.Location = new System.Drawing.Point(148, 227);
|
||||||
|
this.spnWorkItemDuration.Maximum = new decimal(new int[] {
|
||||||
|
6000,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
this.spnWorkItemDuration.Name = "spnWorkItemDuration";
|
||||||
|
this.spnWorkItemDuration.Size = new System.Drawing.Size(72, 24);
|
||||||
|
this.spnWorkItemDuration.TabIndex = 7;
|
||||||
|
this.spnWorkItemDuration.Value = new decimal(new int[] {
|
||||||
|
100,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0});
|
||||||
|
//
|
||||||
|
// label8
|
||||||
|
//
|
||||||
|
this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular);
|
||||||
|
this.label8.Location = new System.Drawing.Point(10, 227);
|
||||||
|
this.label8.Name = "label8";
|
||||||
|
this.label8.Size = new System.Drawing.Size(132, 24);
|
||||||
|
this.label8.Text = "Work item duration (ms)";
|
||||||
|
//
|
||||||
|
// usageControl1
|
||||||
|
//
|
||||||
|
this.usageControl1.BackColor = System.Drawing.Color.Black;
|
||||||
|
this.usageControl1.Location = new System.Drawing.Point(10, 33);
|
||||||
|
this.usageControl1.Maximum = 10;
|
||||||
|
this.usageControl1.Name = "usageControl1";
|
||||||
|
this.usageControl1.Size = new System.Drawing.Size(41, 52);
|
||||||
|
this.usageControl1.TabIndex = 1;
|
||||||
|
this.usageControl1.Value1 = 0;
|
||||||
|
this.usageControl1.Value2 = 0;
|
||||||
|
//
|
||||||
|
// usageHistoryControl1
|
||||||
|
//
|
||||||
|
this.usageHistoryControl1.BackColor = System.Drawing.Color.Black;
|
||||||
|
this.usageHistoryControl1.Location = new System.Drawing.Point(66, 33);
|
||||||
|
this.usageHistoryControl1.Maximum = 10;
|
||||||
|
this.usageHistoryControl1.Name = "usageHistoryControl1";
|
||||||
|
this.usageHistoryControl1.Size = new System.Drawing.Size(154, 52);
|
||||||
|
this.usageHistoryControl1.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// Form1
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||||
|
this.AutoScroll = true;
|
||||||
|
this.ClientSize = new System.Drawing.Size(240, 258);
|
||||||
|
this.Controls.Add(this.btnStartStop);
|
||||||
|
this.Controls.Add(this.spnWorkItemDuration);
|
||||||
|
this.Controls.Add(this.label8);
|
||||||
|
this.Controls.Add(this.spnWorkItemsPerSecond);
|
||||||
|
this.Controls.Add(this.label6);
|
||||||
|
this.Controls.Add(this.spnIdleTimeout);
|
||||||
|
this.Controls.Add(this.spnMaxThreads);
|
||||||
|
this.Controls.Add(this.label4);
|
||||||
|
this.Controls.Add(this.label3);
|
||||||
|
this.Controls.Add(this.label5);
|
||||||
|
this.Controls.Add(this.spnMinThreads);
|
||||||
|
this.Controls.Add(this.lblThreadsInUse);
|
||||||
|
this.Controls.Add(this.label7);
|
||||||
|
this.Controls.Add(this.lblThreadsInPool);
|
||||||
|
this.Controls.Add(this.label2);
|
||||||
|
this.Controls.Add(this.usageControl1);
|
||||||
|
this.Controls.Add(this.label1);
|
||||||
|
this.Controls.Add(this.usageHistoryControl1);
|
||||||
|
this.Menu = this.mainMenu1;
|
||||||
|
this.Name = "Form1";
|
||||||
|
this.Text = "Smart Thread Pool";
|
||||||
|
this.Load += new System.EventHandler(this.Form1_Load);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private UsageControl.UsageControl usageControl1;
|
||||||
|
private Label lblThreadsInUse;
|
||||||
|
private Label label7;
|
||||||
|
private Label lblThreadsInPool;
|
||||||
|
private Label label2;
|
||||||
|
private NumericUpDown spnMinThreads;
|
||||||
|
private Label label4;
|
||||||
|
private Label label3;
|
||||||
|
private Label label5;
|
||||||
|
private NumericUpDown spnMaxThreads;
|
||||||
|
private NumericUpDown spnIdleTimeout;
|
||||||
|
private NumericUpDown spnWorkItemsPerSecond;
|
||||||
|
private Label label6;
|
||||||
|
private NumericUpDown spnWorkItemDuration;
|
||||||
|
private Label label8;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Amib.Threading;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace STPCEDemo
|
||||||
|
{
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
private bool running;
|
||||||
|
private readonly System.Windows.Forms.Timer uiTimer;
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private readonly System.Windows.Forms.Timer wiTimer;
|
||||||
|
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
uiTimer = new System.Windows.Forms.Timer();
|
||||||
|
uiTimer.Interval = 1000;
|
||||||
|
uiTimer.Tick += new EventHandler(uiTimer_Tick);
|
||||||
|
|
||||||
|
wiTimer = new System.Windows.Forms.Timer();
|
||||||
|
wiTimer.Interval = 1000;
|
||||||
|
wiTimer.Tick += new EventHandler(wiTimer_Tick);
|
||||||
|
//Debug.WriteLine("Form Thread Priority is " + (int)GetCurrentThreadPriority());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Form1_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SetRunningState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (null == _stp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int inUse = _stp.InUseThreads;
|
||||||
|
int inPool = _stp.ActiveThreads;
|
||||||
|
|
||||||
|
this.usageHistoryControl1.AddValues(inUse, inPool);
|
||||||
|
this.usageControl1.Value1 = inUse;
|
||||||
|
this.usageControl1.Value2 = inPool;
|
||||||
|
this.lblThreadsInUse.Text = inUse.ToString();
|
||||||
|
this.lblThreadsInPool.Text = inPool.ToString();
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wiTimer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
int count = Convert.ToInt32(spnWorkItemsPerSecond.Value);
|
||||||
|
int sleepDuration = Convert.ToInt32(spnWorkItemDuration.Value);
|
||||||
|
Debug.WriteLine(string.Format("{0}: C = {1}, S = {2}", DateTime.Now.ToString("HH:mm:ss"), count, sleepDuration));
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
_stp.QueueWorkItem(DoWork, sleepDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoWork(int sleepDuration)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("DoWork Thread Priority is " + (int)GetCurrentThreadPriority());
|
||||||
|
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
//int sleepDuration = Convert.ToInt32(state);
|
||||||
|
Thread.Sleep(sleepDuration);
|
||||||
|
TimeSpan duration = DateTime.Now - start;
|
||||||
|
|
||||||
|
Debug.WriteLine(string.Format("{0}: Duration = {1}", DateTime.Now.ToString("HH:mm:ss"), duration.TotalMilliseconds));
|
||||||
|
|
||||||
|
//return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void btnStartStop_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SetRunningState(!running);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetRunningState(bool newRunningState)
|
||||||
|
{
|
||||||
|
btnStartStop.Text = newRunningState ? "Stop" : "Start";
|
||||||
|
if (newRunningState)
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool(
|
||||||
|
Convert.ToInt32(spnIdleTimeout.Value) * 1000,
|
||||||
|
Convert.ToInt32(spnMaxThreads.Value),
|
||||||
|
Convert.ToInt32(spnMinThreads.Value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (null != _stp)
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
_stp = null;
|
||||||
|
}
|
||||||
|
spnIdleTimeout.Enabled = !newRunningState;
|
||||||
|
uiTimer.Enabled = newRunningState;
|
||||||
|
wiTimer.Enabled = newRunningState;
|
||||||
|
running = newRunningState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spnMinThreads_ValueChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (null != _stp)
|
||||||
|
{
|
||||||
|
_stp.MinThreads = Convert.ToInt32(spnMinThreads.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spnMaxThreads_ValueChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (null != _stp)
|
||||||
|
{
|
||||||
|
_stp.MaxThreads = Convert.ToInt32(spnMaxThreads.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetCurrentThreadPriority()
|
||||||
|
{
|
||||||
|
IntPtr hThread = GetCurrentThread();
|
||||||
|
int priority = CeGetThreadPriority(hThread);
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("coredll.dll", SetLastError = true)]
|
||||||
|
public static extern int CeGetThreadPriority(IntPtr hThread);
|
||||||
|
|
||||||
|
[DllImport("coredll.dll")]
|
||||||
|
public static extern IntPtr GetCurrentThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="mainMenu1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="$this.FormFactorShadowProperty" xml:space="preserve">
|
||||||
|
<value>WEBPAD</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="$this.Skin" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace STPCEDemo
|
||||||
|
{
|
||||||
|
public static class Pens
|
||||||
|
{
|
||||||
|
private static Pen _red = new Pen(Color.Red);
|
||||||
|
private static Pen _lawnGreen = new Pen(Color.LawnGreen);
|
||||||
|
|
||||||
|
private static Pen _green = new Pen(Color.Green);
|
||||||
|
private static Pen _darkGray = new Pen(Color.DarkGray);
|
||||||
|
private static Pen _white = new Pen(Color.White);
|
||||||
|
|
||||||
|
|
||||||
|
public static Pen Red
|
||||||
|
{
|
||||||
|
get { return _red; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Pen LawnGreen
|
||||||
|
{
|
||||||
|
get { return _lawnGreen; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pen Green
|
||||||
|
{
|
||||||
|
get { return _green; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pen DarkGray
|
||||||
|
{
|
||||||
|
get { return _darkGray; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pen White
|
||||||
|
{
|
||||||
|
get { return _white; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace STPCEDemo
|
||||||
|
{
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[MTAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
Application.Run(new Form1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("STPCEDemo")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("STPCEDemo")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2008")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("a9f7d57c-9b87-4b5e-81a5-9d4b2719b5b5")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:2.0.50727.1433
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace STPCEDemo.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("STPCEDemo.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.50727</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{356114BA-5F10-4DB6-9971-987CE11F765F}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>STPCEDemo</RootNamespace>
|
||||||
|
<AssemblyName>STPCEDemo</AssemblyName>
|
||||||
|
<ProjectTypeGuids>{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
|
||||||
|
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
|
||||||
|
<OSVersion>5.0</OSVersion>
|
||||||
|
<DeployDirSuffix>STPCEDemo</DeployDirSuffix>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FormFactorID>
|
||||||
|
</FormFactorID>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Form1.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Form1.Designer.cs">
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pens.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<EmbeddedResource Include="Form1.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="UsageControl.resx">
|
||||||
|
<DependentUpon>UsageControl.cs</DependentUpon>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="UsageHistoryControl.resx">
|
||||||
|
<DependentUpon>UsageHistoryControl.cs</DependentUpon>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="UsageControl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="UsageHistoryControl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SmartThreadPool\SmartThreadPoolCE.csproj">
|
||||||
|
<Project>{D81DD596-C71F-4AC2-816C-63C19589E7E0}</Project>
|
||||||
|
<Name>SmartThreadPoolCE</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Condition="'$(TargetFrameworkVersion)' == 'v1.0'" Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.v1.targets" />
|
||||||
|
<Import Condition="'$(TargetFrameworkVersion)' == 'v2.0'" Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<FlavorProperties GUID="{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}">
|
||||||
|
<HostingProcess disable="1" />
|
||||||
|
</FlavorProperties>
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Data;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using STPCEDemo;
|
||||||
|
|
||||||
|
namespace UsageControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for UsageControl.
|
||||||
|
/// </summary>
|
||||||
|
public class UsageControl : System.Windows.Forms.UserControl
|
||||||
|
{
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
private const int ovalWidth = 18;
|
||||||
|
private const int columns = 2;
|
||||||
|
|
||||||
|
private int fixedWidth;
|
||||||
|
private int rows = 1;
|
||||||
|
|
||||||
|
private int min = 0; // Minimum value for progress range
|
||||||
|
private int max = 100; // Maximum value for progress range
|
||||||
|
private int val1 = 0; // Current progress
|
||||||
|
private int val2 = 0; // Current progress
|
||||||
|
|
||||||
|
public UsageControl()
|
||||||
|
{
|
||||||
|
// This call is required by the Windows.Forms Form Designer.
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
EnableDoubleBuffering();
|
||||||
|
fixedWidth = 2 + (ovalWidth+1)*columns + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Dispose( bool disposing )
|
||||||
|
{
|
||||||
|
if( disposing )
|
||||||
|
{
|
||||||
|
if(components != null)
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose( disposing );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnableDoubleBuffering()
|
||||||
|
{
|
||||||
|
// Set the value of the double-buffering style bits to true.
|
||||||
|
//this.SetStyle(ControlStyles.DoubleBuffer |
|
||||||
|
// ControlStyles.UserPaint |
|
||||||
|
// ControlStyles.AllPaintingInWmPaint,
|
||||||
|
// true);
|
||||||
|
//this.UpdateStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// UsageControl
|
||||||
|
//
|
||||||
|
this.BackColor = System.Drawing.Color.Black;
|
||||||
|
this.Name = "UsageControl";
|
||||||
|
this.Size = new System.Drawing.Size(192, 160);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected override void OnResize(EventArgs e)
|
||||||
|
{
|
||||||
|
Width = fixedWidth;
|
||||||
|
rows = (ClientRectangle.Height / 4) - 1;
|
||||||
|
// Invalidate the control to get a repaint.
|
||||||
|
this.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
Graphics g = e.Graphics;
|
||||||
|
|
||||||
|
int percent1 = ((val1 - min) * 100) / (max - min);
|
||||||
|
int percent2 = ((val2 - min) * 100) / (max - min);
|
||||||
|
|
||||||
|
int filledCount1 = (rows * percent1) / 100;
|
||||||
|
int filledCount2 = (rows * percent2) / 100;
|
||||||
|
int diff = Math.Abs(filledCount1 - filledCount2);
|
||||||
|
|
||||||
|
int emptyCount = rows - Math.Max(filledCount1, filledCount2);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < filledCount1; ++i)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < columns; ++j)
|
||||||
|
{
|
||||||
|
DrawOval(
|
||||||
|
g,
|
||||||
|
Pens.LawnGreen,
|
||||||
|
2 + j*(1+ovalWidth),
|
||||||
|
ClientRectangle.Bottom - 5 - i*4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < filledCount2; ++i)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < columns; ++j)
|
||||||
|
{
|
||||||
|
DrawOval(
|
||||||
|
g,
|
||||||
|
Pens.Red,
|
||||||
|
2 + j*(1+ovalWidth),
|
||||||
|
ClientRectangle.Bottom - 5 - i*4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; i < rows; ++i)
|
||||||
|
{
|
||||||
|
for(int j = 0; j < columns; ++j)
|
||||||
|
{
|
||||||
|
DrawOval(
|
||||||
|
g,
|
||||||
|
Pens.Green,
|
||||||
|
2 + j*(1+ovalWidth),
|
||||||
|
ClientRectangle.Bottom - 5 - i*4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a three-dimensional border around the control.
|
||||||
|
Draw3DBorder(g);
|
||||||
|
|
||||||
|
// Clean up.
|
||||||
|
//g.Dispose();
|
||||||
|
base.OnPaint (e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawOval(Graphics g, Pen pen, int x, int y)
|
||||||
|
{
|
||||||
|
g.DrawLine(pen, x+1 , y, x+ovalWidth-2, y);
|
||||||
|
g.DrawLine(pen, x, y+1, x+ovalWidth-1, y+1);
|
||||||
|
g.DrawLine(pen, x+1, y+2, x+ovalWidth-2, y+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Maximum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Make sure that the maximum value is never set lower than the minimum value.
|
||||||
|
if (value < min)
|
||||||
|
{
|
||||||
|
min = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
max = value;
|
||||||
|
|
||||||
|
// Make sure that value is still in range.
|
||||||
|
if (val1 > max)
|
||||||
|
{
|
||||||
|
val1 = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate the control to get a repaint.
|
||||||
|
this.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Value1
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return val1;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int oldValue = val1;
|
||||||
|
|
||||||
|
// Make sure that the value does not stray outside the valid range.
|
||||||
|
if (value < min)
|
||||||
|
{
|
||||||
|
val1 = min;
|
||||||
|
}
|
||||||
|
else if (value > max)
|
||||||
|
{
|
||||||
|
val1 = max;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val1 = value;
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
/*
|
||||||
|
// Invalidate only the changed area.
|
||||||
|
float percent;
|
||||||
|
|
||||||
|
Rectangle newValueRect = this.ClientRectangle;
|
||||||
|
Rectangle oldValueRect = this.ClientRectangle;
|
||||||
|
|
||||||
|
// Use a new value to calculate the rectangle for progress.
|
||||||
|
percent = (float)(val1 - min) / (float)(max - min);
|
||||||
|
newValueRect.Width = (int)((float)newValueRect.Width * percent);
|
||||||
|
|
||||||
|
// Use an old value to calculate the rectangle for progress.
|
||||||
|
percent = (float)(oldValue - min) / (float)(max - min);
|
||||||
|
oldValueRect.Width = (int)((float)oldValueRect.Width * percent);
|
||||||
|
|
||||||
|
Rectangle updateRect = new Rectangle();
|
||||||
|
|
||||||
|
// Find only the part of the screen that must be updated.
|
||||||
|
if (newValueRect.Width > oldValueRect.Width)
|
||||||
|
{
|
||||||
|
updateRect.X = oldValueRect.Size.Width;
|
||||||
|
updateRect.Width = newValueRect.Width - oldValueRect.Width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateRect.X = newValueRect.Size.Width;
|
||||||
|
updateRect.Width = oldValueRect.Width - newValueRect.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRect.Height = this.Height;
|
||||||
|
|
||||||
|
// Invalidate the intersection region only.
|
||||||
|
this.Invalidate(updateRect);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Value2
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int oldValue = val2;
|
||||||
|
|
||||||
|
// Make sure that the value does not stray outside the valid range.
|
||||||
|
if (value < min)
|
||||||
|
{
|
||||||
|
val2 = min;
|
||||||
|
}
|
||||||
|
else if (value > max)
|
||||||
|
{
|
||||||
|
val2 = max;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
val2 = value;
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Invalidate only the changed area.
|
||||||
|
float percent;
|
||||||
|
|
||||||
|
Rectangle newValueRect = this.ClientRectangle;
|
||||||
|
Rectangle oldValueRect = this.ClientRectangle;
|
||||||
|
|
||||||
|
// Use a new value to calculate the rectangle for progress.
|
||||||
|
percent = (float)(val1 - min) / (float)(max - min);
|
||||||
|
newValueRect.Width = (int)((float)newValueRect.Width * percent);
|
||||||
|
|
||||||
|
// Use an old value to calculate the rectangle for progress.
|
||||||
|
percent = (float)(oldValue - min) / (float)(max - min);
|
||||||
|
oldValueRect.Width = (int)((float)oldValueRect.Width * percent);
|
||||||
|
|
||||||
|
Rectangle updateRect = new Rectangle();
|
||||||
|
|
||||||
|
// Find only the part of the screen that must be updated.
|
||||||
|
if (newValueRect.Width > oldValueRect.Width)
|
||||||
|
{
|
||||||
|
updateRect.X = oldValueRect.Size.Width;
|
||||||
|
updateRect.Width = newValueRect.Width - oldValueRect.Width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateRect.X = newValueRect.Size.Width;
|
||||||
|
updateRect.Width = oldValueRect.Width - newValueRect.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRect.Height = this.Height;
|
||||||
|
|
||||||
|
// Invalidate the intersection region only.
|
||||||
|
this.Invalidate(updateRect);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Draw3DBorder(Graphics g)
|
||||||
|
{
|
||||||
|
int PenWidth = (int)Pens.White.Width;
|
||||||
|
|
||||||
|
g.DrawLine(Pens.DarkGray,
|
||||||
|
this.ClientRectangle.Left, this.ClientRectangle.Top,
|
||||||
|
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top);
|
||||||
|
g.DrawLine(Pens.DarkGray,
|
||||||
|
this.ClientRectangle.Left, this.ClientRectangle.Top,
|
||||||
|
this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth);
|
||||||
|
g.DrawLine(Pens.White,
|
||||||
|
this.ClientRectangle.Left, this.ClientRectangle.Height - PenWidth,
|
||||||
|
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth);
|
||||||
|
g.DrawLine(Pens.White,
|
||||||
|
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Top,
|
||||||
|
this.ClientRectangle.Width - PenWidth, this.ClientRectangle.Height - PenWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used forserialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>80</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>(Default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Name">
|
||||||
|
<value>UsageControl</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>8, 8</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Data;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using STPCEDemo;
|
||||||
|
|
||||||
|
namespace UsageControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for UsageHistoryControl.
|
||||||
|
/// </summary>
|
||||||
|
public class UsageHistoryControl : System.Windows.Forms.UserControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.Container components = null;
|
||||||
|
|
||||||
|
private const int squareWidth = 12;
|
||||||
|
private const int maxLastValuesCount = 2000;
|
||||||
|
private const int shiftStep = 3;
|
||||||
|
|
||||||
|
private int shift = 0;
|
||||||
|
|
||||||
|
private int [] lastValues1 = new int[maxLastValuesCount];
|
||||||
|
private int [] lastValues2 = new int[maxLastValuesCount];
|
||||||
|
private int nextValueIndex;
|
||||||
|
private int lastValuesCount;
|
||||||
|
|
||||||
|
private int max = 100;
|
||||||
|
private int min = 0;
|
||||||
|
|
||||||
|
public UsageHistoryControl()
|
||||||
|
{
|
||||||
|
// This call is required by the Windows.Forms Form Designer.
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
EnableDoubleBuffering();
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
lastValues1.Initialize();
|
||||||
|
lastValues2.Initialize();
|
||||||
|
nextValueIndex = 0;
|
||||||
|
lastValuesCount = 0;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
protected override void Dispose( bool disposing )
|
||||||
|
{
|
||||||
|
if( disposing )
|
||||||
|
{
|
||||||
|
if(components != null)
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose( disposing );
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// UsageHistoryControl
|
||||||
|
//
|
||||||
|
this.BackColor = System.Drawing.Color.Black;
|
||||||
|
this.Name = "UsageHistoryControl";
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void EnableDoubleBuffering()
|
||||||
|
{
|
||||||
|
// Set the value of the double-buffering style bits to true.
|
||||||
|
//this.SetStyle(ControlStyles.DoubleBuffer |
|
||||||
|
// ControlStyles.UserPaint |
|
||||||
|
// ControlStyles.AllPaintingInWmPaint,
|
||||||
|
// true);
|
||||||
|
//this.UpdateStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResize(EventArgs e)
|
||||||
|
{
|
||||||
|
// Invalidate the control to get a repaint.
|
||||||
|
this.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
Graphics g = e.Graphics;
|
||||||
|
|
||||||
|
for(int i = 0; i <= ClientRectangle.Width+squareWidth; i += squareWidth)
|
||||||
|
{
|
||||||
|
g.DrawLine(Pens.Green, i-shift, 0, i-shift, ClientRectangle.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < ClientRectangle.Height; i += squareWidth)
|
||||||
|
{
|
||||||
|
g.DrawLine(Pens.Green, 0, i, ClientRectangle.Width, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int startValueIndex = (nextValueIndex-1+maxLastValuesCount)%maxLastValuesCount;
|
||||||
|
|
||||||
|
int prevVal1 = GetRelativeValue(lastValues1[startValueIndex]);
|
||||||
|
int prevVal2 = GetRelativeValue(lastValues2[startValueIndex]);
|
||||||
|
|
||||||
|
for(int i = 1; i < lastValuesCount; ++i)
|
||||||
|
{
|
||||||
|
int index = nextValueIndex - 1 - i;
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
index += maxLastValuesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int val1 = GetRelativeValue(lastValues1[index]);
|
||||||
|
int val2 = GetRelativeValue(lastValues2[index]);
|
||||||
|
|
||||||
|
g.DrawLine(
|
||||||
|
Pens.Red,
|
||||||
|
ClientRectangle.Width-(i-1)*shiftStep, ClientRectangle.Height-prevVal2,
|
||||||
|
ClientRectangle.Width-i*shiftStep, ClientRectangle.Height-val2);
|
||||||
|
|
||||||
|
g.DrawLine(
|
||||||
|
Pens.LawnGreen,
|
||||||
|
ClientRectangle.Width-(i-1)*shiftStep, ClientRectangle.Height-prevVal1,
|
||||||
|
ClientRectangle.Width-i*shiftStep, ClientRectangle.Height-val1);
|
||||||
|
|
||||||
|
prevVal1 = val1;
|
||||||
|
prevVal2 = val2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetRelativeValue(int val)
|
||||||
|
{
|
||||||
|
int result = val * (ClientRectangle.Height-2) / max + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddValues(int val1, int val2)
|
||||||
|
{
|
||||||
|
lastValues1[nextValueIndex] = val1;
|
||||||
|
lastValues2[nextValueIndex] = val2;
|
||||||
|
|
||||||
|
nextValueIndex++;
|
||||||
|
nextValueIndex %= maxLastValuesCount;
|
||||||
|
lastValuesCount++;
|
||||||
|
if (lastValuesCount > maxLastValuesCount)
|
||||||
|
{
|
||||||
|
lastValuesCount = maxLastValuesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
shift += shiftStep;
|
||||||
|
shift %= squareWidth;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Maximum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Make sure that the maximum value is never set lower than the minimum value.
|
||||||
|
if (value < min)
|
||||||
|
{
|
||||||
|
min = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
max = value;
|
||||||
|
|
||||||
|
// Invalidate the control to get a repaint.
|
||||||
|
this.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 1.3
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">1.3</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1">this is my long string</data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
[base64 mime encoded serialized .NET Framework object]
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used forserialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>1.3</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>True</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Name">
|
||||||
|
<value>UsageHistoryControl</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>80</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>(Default)</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>False</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>Private</value>
|
||||||
|
</data>
|
||||||
|
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>8, 8</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -6,27 +6,15 @@ namespace Examples
|
|||||||
{
|
{
|
||||||
public class CatchExceptionExample
|
public class CatchExceptionExample
|
||||||
{
|
{
|
||||||
private class DivArgs
|
|
||||||
{
|
|
||||||
public int x;
|
|
||||||
public int y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DoWork()
|
public void DoWork()
|
||||||
{
|
{
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
DivArgs divArgs = new DivArgs();
|
IWorkItemResult<double> wir = smartThreadPool.QueueWorkItem(new Func<double, double, double>(DoDiv), 10.0, 0.0);
|
||||||
divArgs.x = 10;
|
|
||||||
divArgs.y = 0;
|
|
||||||
|
|
||||||
IWorkItemResult wir =
|
|
||||||
smartThreadPool.QueueWorkItem(new
|
|
||||||
WorkItemCallback(this.DoDiv), divArgs);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int result = (int)wir.Result;
|
double result = wir.Result;
|
||||||
}
|
}
|
||||||
// Catch the exception that Result threw
|
// Catch the exception that Result threw
|
||||||
catch (WorkItemResultException e)
|
catch (WorkItemResultException e)
|
||||||
@@ -38,10 +26,9 @@ namespace Examples
|
|||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DoDiv(object state)
|
private double DoDiv(double x, double y)
|
||||||
{
|
{
|
||||||
DivArgs divArgs = (DivArgs)state;
|
return x / y;
|
||||||
return (divArgs.x / divArgs.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace Examples
|
||||||
|
{
|
||||||
|
public class CooperativeCancelExample
|
||||||
|
{
|
||||||
|
public void DoWork(object state)
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(DoRealWork);
|
||||||
|
|
||||||
|
// Give the work item some time to complete.
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
|
// If the work item hasn't completed yet then cancel it.
|
||||||
|
if (!wir.IsCompleted)
|
||||||
|
{
|
||||||
|
wir.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do some lengthy work
|
||||||
|
private void DoRealWork()
|
||||||
|
{
|
||||||
|
// Do something here.
|
||||||
|
|
||||||
|
// Sample SmartThreadPool.IsWorkItemCanceled
|
||||||
|
if (SmartThreadPool.IsWorkItemCanceled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample the SmartThreadPool.IsWorkItemCanceled in a loop
|
||||||
|
while (!SmartThreadPool.IsWorkItemCanceled)
|
||||||
|
{
|
||||||
|
// Do some real work here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace STPExamples
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is a Parallel QuickSort example.
|
||||||
|
/// It shows how to use the QueueWorkItem with Action<T> methods.
|
||||||
|
/// </summary>
|
||||||
|
public class ParallelQuickSort
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// Generate an array
|
||||||
|
int[] array = GenerateArray(100);
|
||||||
|
|
||||||
|
// Create a Smart Thread Pool
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
|
||||||
|
// Use the Smart Thread Pool to parallel the sort
|
||||||
|
QuickSort(stp, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// QuickSort array using wig to parallel the sort
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wig">A IWorkItemsGroup to use to parallel the sort</param>
|
||||||
|
/// <param name="array">The array of items to sort</param>
|
||||||
|
public static void QuickSort(IWorkItemsGroup wig, int[] array)
|
||||||
|
{
|
||||||
|
// Initiate the QuickSort
|
||||||
|
wig.QueueWorkItem(QuickSort, wig, array, 0, array.Length - 1);
|
||||||
|
|
||||||
|
// Wait for the sort to complete.
|
||||||
|
wig.WaitForIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sort a subarray in array, starting with the left item and ending in the right item.
|
||||||
|
/// The method uses the IWorkItemsGroup wig to parallel the sort.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wig">A IWorkItemsGroup to use to parallel the sort</param>
|
||||||
|
/// <param name="array">The array of items to sort</param>
|
||||||
|
/// <param name="left">The left index in the subarray</param>
|
||||||
|
/// <param name="right">The right index in the subarray</param>
|
||||||
|
private static void QuickSort(IWorkItemsGroup wig, int[] array, int left, int right)
|
||||||
|
{
|
||||||
|
if (right > left)
|
||||||
|
{
|
||||||
|
int pivotIndex = left;
|
||||||
|
int pivotNewIndex = Partition(array, left, right, pivotIndex);
|
||||||
|
|
||||||
|
wig.QueueWorkItem(QuickSort, wig, array, left, pivotNewIndex - 1);
|
||||||
|
wig.QueueWorkItem(QuickSort, wig, array, pivotNewIndex + 1, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partition a subarray of array
|
||||||
|
/// (This is part of the QuickSort algorithm)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static int Partition(int[] array, int left, int right, int pivotIndex)
|
||||||
|
{
|
||||||
|
int pivotValue = array[pivotIndex];
|
||||||
|
Swap(array, pivotIndex, right);
|
||||||
|
int storeIndex = left;
|
||||||
|
|
||||||
|
for (int i = left; i < right; i++)
|
||||||
|
{
|
||||||
|
if (array[i] <= pivotValue)
|
||||||
|
{
|
||||||
|
Swap(array, i, storeIndex);
|
||||||
|
++storeIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Swap(array, storeIndex, right);
|
||||||
|
return storeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Swap between two item in the array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="array">Array of integers</param>
|
||||||
|
/// <param name="index1">First index</param>
|
||||||
|
/// <param name="index2">Second index</param>
|
||||||
|
private static void Swap(int[] array, int index1, int index2)
|
||||||
|
{
|
||||||
|
int temp = array[index1];
|
||||||
|
array[index1] = array[index2];
|
||||||
|
array[index2] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate an array with the numbers 0-count ordered in reverse
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The number of items in the array</param>
|
||||||
|
/// <returns>Returns the generated array</returns>
|
||||||
|
private static int[] GenerateArray(int count)
|
||||||
|
{
|
||||||
|
int[] array = new int[count];
|
||||||
|
for (int i = 0; i < array.Length; i++)
|
||||||
|
{
|
||||||
|
array[i] = array.Length - i;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,11 +16,10 @@
|
|||||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||||
<DelaySign>false</DelaySign>
|
<DelaySign>false</DelaySign>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>STPExamples</RootNamespace>
|
<RootNamespace>STPExamples</RootNamespace>
|
||||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||||
<StartupObject>
|
<StartupObject>STPExamples.ParallelQuickSort</StartupObject>
|
||||||
</StartupObject>
|
|
||||||
<FileUpgradeFlags>
|
<FileUpgradeFlags>
|
||||||
</FileUpgradeFlags>
|
</FileUpgradeFlags>
|
||||||
<UpgradeBackupLocation>
|
<UpgradeBackupLocation>
|
||||||
@@ -72,6 +71,16 @@
|
|||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>
|
||||||
|
</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System">
|
<Reference Include="System">
|
||||||
<Name>System</Name>
|
<Name>System</Name>
|
||||||
@@ -79,6 +88,10 @@
|
|||||||
<Reference Include="System.Data">
|
<Reference Include="System.Data">
|
||||||
<Name>System.Data</Name>
|
<Name>System.Data</Name>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\..\..\..\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\2.0\v2.0\WindowsCE\System.Drawing.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Xml">
|
<Reference Include="System.Xml">
|
||||||
<Name>System.XML</Name>
|
<Name>System.XML</Name>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -96,12 +109,14 @@
|
|||||||
<Compile Include="CatchExceptionExample.cs">
|
<Compile Include="CatchExceptionExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="CooperativeCancelExample.cs" />
|
||||||
<Compile Include="GetExceptionExample.cs">
|
<Compile Include="GetExceptionExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="OnWIGIdleEventExample.cs">
|
<Compile Include="OnWIGIdleEventExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ParallelQuickSort.cs" />
|
||||||
<Compile Include="PriorityExample.cs">
|
<Compile Include="PriorityExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -114,6 +129,7 @@
|
|||||||
<Compile Include="SuspendedWIGStartExample.cs">
|
<Compile Include="SuspendedWIGStartExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ThreadEventsExample.cs" />
|
||||||
<Compile Include="WaitForAllExample.cs">
|
<Compile Include="WaitForAllExample.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -1,35 +1,34 @@
|
|||||||
|
using System;
|
||||||
using Amib.Threading;
|
using Amib.Threading;
|
||||||
|
|
||||||
namespace Examples
|
namespace Examples
|
||||||
{
|
{
|
||||||
public class SimpleExample
|
public class SimpleExample
|
||||||
{
|
{
|
||||||
public void DoWork(object state)
|
public void DoWork(int[] numbers)
|
||||||
{
|
{
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
// Queue the work item
|
// Queue the work item
|
||||||
IWorkItemResult wir =
|
IWorkItemResult<double> wir = smartThreadPool.QueueWorkItem(new Func<int[], double>(CalcAverage), numbers);
|
||||||
smartThreadPool.QueueWorkItem(
|
|
||||||
new WorkItemCallback(this.DoRealWork),
|
|
||||||
state);
|
|
||||||
|
|
||||||
// Do some other work here
|
// Do some other work here
|
||||||
|
|
||||||
// Get the result of the operation
|
// Get the result of the operation
|
||||||
object result = wir.Result;
|
double average = wir.Result;
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the real work
|
// Do the real work
|
||||||
private object DoRealWork(object state)
|
private double CalcAverage(int[] numbers)
|
||||||
{
|
{
|
||||||
object result = null;
|
double average = 0.0;
|
||||||
|
|
||||||
// Do the real work here and put the result in 'result'
|
// Do the real work here and put
|
||||||
|
// the result in 'result'
|
||||||
|
|
||||||
return result;
|
return average;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace STPExamples
|
||||||
|
{
|
||||||
|
public class MyResource : IDisposable
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
|
||||||
|
public void DoIt()
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ThreadEventsExample
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
stp.OnThreadInitialization += new ThreadInitializationHandler(OnInitialization);
|
||||||
|
stp.OnThreadTermination += new ThreadTerminationHandler(OnTermination);
|
||||||
|
|
||||||
|
stp.QueueWorkItem(DoSomeWork);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static MyResource _resource;
|
||||||
|
|
||||||
|
public static void OnInitialization()
|
||||||
|
{
|
||||||
|
// Initialize the resource
|
||||||
|
_resource = new MyResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
// Use the resouce
|
||||||
|
_resource.DoIt();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnTermination()
|
||||||
|
{
|
||||||
|
// Do resource cleanup
|
||||||
|
_resource.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,693 @@
|
|||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
#pragma warning disable 168
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
public static class QueueWorkItemHelper
|
||||||
|
{
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
public static void TestQueueWorkItemCall(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(wiic.CompareWorkItemInfo);
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
|
public static void TestQueueWorkItemCallPrio(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.WorkItemPriority = WorkItemPriority.AboveNormal;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem((WorkItemCallback)wiic.CompareWorkItemInfo, WorkItemPriority.AboveNormal);
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
|
public static void TestQueueWorkItemCallStat(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
object state = new object();
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem((WorkItemCallback) wiic.CompareWorkItemInfo, state);
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
|
public static void TestQueueWorkItemCallStatPrio(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
object state = new object();
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.WorkItemPriority = WorkItemPriority.AboveNormal;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(wiic.CompareWorkItemInfo, state, WorkItemPriority.AboveNormal);
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
|
public static void TestQueueWorkItemCallStatPost(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
bool postExecuteCalled = false;
|
||||||
|
object state = new object();
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback = delegate(IWorkItemResult w) { postExecuteCalled = true; };
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
|
public static void TestQueueWorkItemCallStatPostPrio(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
bool postExecuteCalled = false;
|
||||||
|
object state = new object();
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback = delegate(IWorkItemResult w) { postExecuteCalled = true; };
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.WorkItemPriority = WorkItemPriority.BelowNormal;
|
||||||
|
wii.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
WorkItemPriority.BelowNormal);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
|
public static void TestQueueWorkItemCallStatPostPflg(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
bool postExecuteCalled;
|
||||||
|
CallToPostExecute callToPostExecute;
|
||||||
|
object state = new object();
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback = delegate(IWorkItemResult w) { postExecuteCalled = true; };
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
IWorkItemResult wir;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.Always;
|
||||||
|
|
||||||
|
// Check without cancel
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.Never;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.WhenWorkItemNotCanceled;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.WhenWorkItemCanceled;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
|
public static void TestQueueWorkItemCallStatPostPflgPrio(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
bool postExecuteCalled;
|
||||||
|
CallToPostExecute callToPostExecute;
|
||||||
|
object state = new object();
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback = delegate(IWorkItemResult w) { postExecuteCalled = true; };
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
WorkItemPriority workItemPriority;
|
||||||
|
IWorkItemResult wir;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.Always;
|
||||||
|
workItemPriority = WorkItemPriority.Lowest;
|
||||||
|
|
||||||
|
// Check without cancel
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
wii.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.Never;
|
||||||
|
workItemPriority = WorkItemPriority.Highest;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
wii.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.WhenWorkItemNotCanceled;
|
||||||
|
workItemPriority = WorkItemPriority.AboveNormal;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
wii.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
callToPostExecute = CallToPostExecute.WhenWorkItemCanceled;
|
||||||
|
workItemPriority = WorkItemPriority.BelowNormal;
|
||||||
|
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 0;
|
||||||
|
|
||||||
|
wii.CallToPostExecute = callToPostExecute;
|
||||||
|
wii.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
Assert.IsFalse(postExecuteCalled);
|
||||||
|
|
||||||
|
// Check with cancel
|
||||||
|
success = false;
|
||||||
|
postExecuteCalled = false;
|
||||||
|
wiic.SleepTime = 100;
|
||||||
|
|
||||||
|
wir = wig.QueueWorkItem(
|
||||||
|
wiic.CompareWorkItemInfo,
|
||||||
|
state,
|
||||||
|
postExecuteWorkItemCallback,
|
||||||
|
callToPostExecute,
|
||||||
|
workItemPriority);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.IsTrue(postExecuteCalled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
|
public static void TestQueueWorkItemInfoCall(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.CallToPostExecute = CallToPostExecute.Never;
|
||||||
|
wii.DisposeOfStateObjects = true;
|
||||||
|
wii.PostExecuteWorkItemCallback = delegate(IWorkItemResult w) { };
|
||||||
|
wii.UseCallerCallContext = true;
|
||||||
|
wii.UseCallerHttpContext = true;
|
||||||
|
wii.WorkItemPriority = WorkItemPriority.Highest;
|
||||||
|
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(wii, wiic.CompareWorkItemInfo);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
|
public static void TestQueueWorkItemInfoCallStat(IWorkItemsGroup wig)
|
||||||
|
{
|
||||||
|
object state = new object();
|
||||||
|
WorkItemInfo wii = new WorkItemInfo();
|
||||||
|
wii.CallToPostExecute = CallToPostExecute.Never;
|
||||||
|
wii.DisposeOfStateObjects = true;
|
||||||
|
wii.PostExecuteWorkItemCallback = delegate(IWorkItemResult w) { };
|
||||||
|
wii.UseCallerCallContext = true;
|
||||||
|
wii.UseCallerHttpContext = true;
|
||||||
|
wii.WorkItemPriority = WorkItemPriority.Highest;
|
||||||
|
|
||||||
|
WorkItemInfoComparer wiic = new WorkItemInfoComparer(wii, state);
|
||||||
|
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(wii, wiic.CompareWorkItemInfo, state);
|
||||||
|
|
||||||
|
// We must wait for idle to let the post execute run
|
||||||
|
wig.WaitForIdle();
|
||||||
|
|
||||||
|
bool success = (bool)wir.Result;
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorkItemInfo GetCurrentWorkItemInfo()
|
||||||
|
{
|
||||||
|
object threadEntry = typeof(SmartThreadPool).GetField("_threadEntry", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
|
||||||
|
object workitem = threadEntry.GetType().GetField("_currentWorkItem", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(threadEntry);
|
||||||
|
WorkItemInfo wii = (WorkItemInfo)workitem.GetType().GetField("_workItemInfo", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(workitem);
|
||||||
|
return wii;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WorkItemInfoComparer
|
||||||
|
{
|
||||||
|
private WorkItemInfo _neededWorkItemInfo;
|
||||||
|
private object _state;
|
||||||
|
private int _sleepTime = 0;
|
||||||
|
|
||||||
|
public int SleepTime
|
||||||
|
{
|
||||||
|
get { return _sleepTime; }
|
||||||
|
set { _sleepTime = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemInfoComparer(WorkItemInfo workItemInfo)
|
||||||
|
{
|
||||||
|
_neededWorkItemInfo = workItemInfo;
|
||||||
|
_state = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemInfoComparer(WorkItemInfo workItemInfo, object state)
|
||||||
|
{
|
||||||
|
_neededWorkItemInfo = workItemInfo;
|
||||||
|
_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object CompareWorkItemInfo(object state)
|
||||||
|
{
|
||||||
|
bool equals = object.Equals(_state, state);
|
||||||
|
if (equals)
|
||||||
|
{
|
||||||
|
WorkItemInfo currentWorkItemInfo = GetCurrentWorkItemInfo();
|
||||||
|
equals = CompareWorkItemInfo(currentWorkItemInfo, _neededWorkItemInfo);
|
||||||
|
}
|
||||||
|
if (_sleepTime > 0)
|
||||||
|
{
|
||||||
|
Thread.Sleep(_sleepTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return equals;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CompareWorkItemInfo(WorkItemInfo wii1, WorkItemInfo wii2)
|
||||||
|
{
|
||||||
|
bool equal = true;
|
||||||
|
equal = equal && (wii1.CallToPostExecute == wii2.CallToPostExecute);
|
||||||
|
equal = equal && (wii1.DisposeOfStateObjects == wii2.DisposeOfStateObjects);
|
||||||
|
equal = equal && (wii1.PostExecuteWorkItemCallback == wii2.PostExecuteWorkItemCallback);
|
||||||
|
equal = equal && (wii1.UseCallerCallContext == wii2.UseCallerCallContext);
|
||||||
|
equal = equal && (wii1.UseCallerHttpContext == wii2.UseCallerHttpContext);
|
||||||
|
equal = equal && (wii1.WorkItemPriority == wii2.WorkItemPriority);
|
||||||
|
|
||||||
|
return equal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<DocumentationFile>
|
<DocumentationFile>
|
||||||
</DocumentationFile>
|
</DocumentationFile>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<FileAlignment>4096</FileAlignment>
|
<FileAlignment>4096</FileAlignment>
|
||||||
<NoStdLib>false</NoStdLib>
|
<NoStdLib>false</NoStdLib>
|
||||||
<NoWarn>
|
<NoWarn>
|
||||||
@@ -70,11 +70,21 @@
|
|||||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<DebugType>none</DebugType>
|
<DebugType>full</DebugType>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="nunit.framework, Version=2.2.5.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
<Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
|
||||||
<Reference Include="System">
|
<Reference Include="System">
|
||||||
<Name>System</Name>
|
<Name>System</Name>
|
||||||
</Reference>
|
</Reference>
|
||||||
@@ -94,12 +104,26 @@
|
|||||||
<Compile Include="AssemblyInfo.cs">
|
<Compile Include="AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="TestFalseFillStateWithParams.cs" />
|
||||||
|
<Compile Include="TestFillStateWithParams.cs" />
|
||||||
|
<Compile Include="TestWIGFillStateWithParams.cs" />
|
||||||
|
<Compile Include="TestWIGActionT.cs" />
|
||||||
|
<Compile Include="TestWIGFuncT.cs" />
|
||||||
|
<Compile Include="TestActionT.cs" />
|
||||||
|
<Compile Include="TestFuncT.cs" />
|
||||||
|
<Compile Include="TestWIGQueueWorkItem.cs" />
|
||||||
|
<Compile Include="QueueWorkItemHelper.cs" />
|
||||||
|
<Compile Include="TestQueueWorkItem.cs" />
|
||||||
|
<Compile Include="TestCancel.cs" />
|
||||||
|
<Compile Include="TestConcurrencyChanges.cs" />
|
||||||
<Compile Include="PermutationGenerator.cs">
|
<Compile Include="PermutationGenerator.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="TestChainedDelegates.cs">
|
<Compile Include="TestChainedDelegates.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="TestThreadsCreate.cs" />
|
||||||
|
<Compile Include="TestWIGConcurrencyChanges.cs" />
|
||||||
<Compile Include="TestExceptions.cs">
|
<Compile Include="TestExceptions.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestCancel.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestActionT")]
|
||||||
|
public class TestActionT
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private object _result;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT0()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(MaxInt);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT1()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Not, true);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT2()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Concat, "ABC", "xyz");
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, "ABCxyz");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT3()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Substring, "ABCDEF", 1, 2);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, "BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT4()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Subarray, numbers, 1, 2, 3);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, new int[] { 2, 3, 2, 3, 2, 3, });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MaxInt()
|
||||||
|
{
|
||||||
|
_result = int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Not(bool flag)
|
||||||
|
{
|
||||||
|
_result = !flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Concat(string s1, string s2)
|
||||||
|
{
|
||||||
|
_result = s1 + s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Substring(string s, int startIndex, int length)
|
||||||
|
{
|
||||||
|
_result = s.Substring(startIndex, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Subarray(int[] numbers, int startIndex, int length, int repeat)
|
||||||
|
{
|
||||||
|
int[] result = new int[length * repeat];
|
||||||
|
for (int i = 0; i < repeat; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
result[i * length + j] = numbers[startIndex + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,806 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestCancel.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestCancel")]
|
||||||
|
public class TestCancel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP in suspended mode
|
||||||
|
/// 2. Queue work item into the STP
|
||||||
|
/// 3. Cancel the work item
|
||||||
|
/// 4. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void CancelInQueueWorkItem()
|
||||||
|
{
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.StartSuspended = true;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(delegate(object state) { return null; });
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
Assert.IsTrue(wir.IsCanceled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item that takes some time
|
||||||
|
/// 3. Wait for it to start
|
||||||
|
/// 4. Cancel the work item (soft)
|
||||||
|
/// 5. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void CancelInProgressWorkItemSoft()
|
||||||
|
{
|
||||||
|
ManualResetEvent waitToStart = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(
|
||||||
|
delegate(object state) { waitToStart.Set(); Thread.Sleep(100); return null; }
|
||||||
|
);
|
||||||
|
|
||||||
|
waitToStart.WaitOne();
|
||||||
|
|
||||||
|
wir.Cancel(false);
|
||||||
|
|
||||||
|
Assert.IsTrue(wir.IsCanceled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item that:
|
||||||
|
/// a. Sleep for 0.1 seconds
|
||||||
|
/// b. Increment the counter
|
||||||
|
/// 3. Wait for the work item to start
|
||||||
|
/// 4. Cancel the work item (abort)
|
||||||
|
/// 5. Make sure the work item result indicates the work item has been cancelled.
|
||||||
|
/// 6. Make sure the counter incrementation didn't happen
|
||||||
|
/// 7. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void CancelInProgressWorkItemAbort()
|
||||||
|
{
|
||||||
|
ManualResetEvent waitToStart = new ManualResetEvent(false);
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(
|
||||||
|
delegate(object state) { waitToStart.Set() ; Thread.Sleep(100); ++counter; return null; }
|
||||||
|
);
|
||||||
|
|
||||||
|
waitToStart.WaitOne();
|
||||||
|
|
||||||
|
wir.Cancel(true);
|
||||||
|
|
||||||
|
Assert.IsTrue(wir.IsCanceled);
|
||||||
|
|
||||||
|
Assert.AreEqual(counter, 0);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item that takes some time
|
||||||
|
/// 3. Wait for it to start
|
||||||
|
/// 4. Cancel the work item (soft)
|
||||||
|
/// 5. Make sure, in the work item, that SmartThreadPool.IsWorkItemCanceled is true
|
||||||
|
/// 5. Wait for the STP to get idle
|
||||||
|
/// 6. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CancelInProgressWorkItemSoftWithSample()
|
||||||
|
{
|
||||||
|
bool cancelled = false;
|
||||||
|
ManualResetEvent waitToStart = new ManualResetEvent(false);
|
||||||
|
ManualResetEvent waitToComplete = new ManualResetEvent(false);
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(
|
||||||
|
delegate(object state) {
|
||||||
|
waitToStart.Set();
|
||||||
|
Thread.Sleep(100);
|
||||||
|
cancelled = SmartThreadPool.IsWorkItemCanceled;
|
||||||
|
waitToComplete.Set();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
waitToStart.WaitOne();
|
||||||
|
|
||||||
|
wir.Cancel(false);
|
||||||
|
|
||||||
|
waitToComplete.WaitOne();
|
||||||
|
|
||||||
|
Assert.IsTrue(cancelled);
|
||||||
|
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP in suspended mode
|
||||||
|
/// 2. Queue work item into the STP
|
||||||
|
/// 3. Cancel the work item
|
||||||
|
/// 4. Start the STP
|
||||||
|
/// 5. Wait for the STP to get idle
|
||||||
|
/// 6. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// 7. Cancel the work item again
|
||||||
|
/// 8. Work item's GetResult should throw WorkItemCancelException
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void CancelCanceledWorkItem()
|
||||||
|
{
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.StartSuspended = true;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool(stpStartInfo);
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(delegate(object state) { return null; });
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
catch (WorkItemCancelException ce)
|
||||||
|
{
|
||||||
|
ce.GetHashCode();
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.AreEqual(counter, 1);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item into the STP
|
||||||
|
/// 3. Wait for the STP to get idle
|
||||||
|
/// 4. Work item's GetResult should return value
|
||||||
|
/// 4. Cancel the work item
|
||||||
|
/// 5. Work item's GetResult should return value
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CancelCompletedWorkItem()
|
||||||
|
{
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemResult wir = stp.QueueWorkItem(
|
||||||
|
delegate(object state) { return 1; }
|
||||||
|
);
|
||||||
|
|
||||||
|
stp.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.AreEqual(wir.GetResult(), 1);
|
||||||
|
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
Assert.AreEqual(wir.GetResult(), 1);
|
||||||
|
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Zero counter
|
||||||
|
/// 2. Create STP
|
||||||
|
/// 3. Queue 10 work items, that sleep and then increment the counter, into the STP
|
||||||
|
/// 4. Cancel the STP
|
||||||
|
/// 5. Make sure the counter is still zero
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CancelSTPWorkItems()
|
||||||
|
{
|
||||||
|
// I don't use lock on the counter, since any number above 0 is a failure.
|
||||||
|
// In the worst case counter will be equal to 1 which is still not 0.
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
stp.QueueWorkItem(
|
||||||
|
delegate(object state) { Thread.Sleep(500); ++counter; return null; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
stp.Cancel(true);
|
||||||
|
|
||||||
|
Assert.AreEqual(counter, 0);
|
||||||
|
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Zero counter
|
||||||
|
/// 2. Create STP
|
||||||
|
/// 3. Create a WIG
|
||||||
|
/// 4. Queue 10 work items, that sleep and then increment the counter, into the WIG
|
||||||
|
/// 5. Cancel the WIG
|
||||||
|
/// 6. Wait for the WIG to become idle
|
||||||
|
/// 7. Make sure the counter is still zero
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void CancelWIGWorkItems()
|
||||||
|
{
|
||||||
|
// I don't use lock on the counter, since any number above 0 is a failure.
|
||||||
|
// In the worst case counter will be equal to 1 which is still not 0.
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemsGroup wig = stp.CreateWorkItemsGroup(10);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
wig.QueueWorkItem(
|
||||||
|
delegate(object state) { Thread.Sleep(500); ++counter; return null; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
wig.Cancel(true);
|
||||||
|
|
||||||
|
Assert.AreEqual(counter, 0);
|
||||||
|
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Zero global counter
|
||||||
|
/// 2. Create STP
|
||||||
|
/// 3. Create a WIG1 in suspended mode
|
||||||
|
/// 4. Create a WIG2 in suspended mode
|
||||||
|
/// 5. Queue 5 work items, that increment the global counter, into the WIG1
|
||||||
|
/// 6. Queue 7 work items, that increment the global counter, into the WIG2
|
||||||
|
/// 7. Cancel the WIG1
|
||||||
|
/// 8. Start the WIG1
|
||||||
|
/// 9. Start the WIG2
|
||||||
|
/// 10. Wait for the STP to get idle
|
||||||
|
/// 11. Make sure the global counter is 7
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void Cancel1WIGof2WorkItems()
|
||||||
|
{
|
||||||
|
int counter1 = 0;
|
||||||
|
int counter2 = 0;
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemsGroup wig1 = stp.CreateWorkItemsGroup(3);
|
||||||
|
IWorkItemsGroup wig2 = stp.CreateWorkItemsGroup(3);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
wig1.QueueWorkItem(
|
||||||
|
delegate(object state) { Interlocked.Increment(ref counter1); Thread.Sleep(500); Interlocked.Increment(ref counter1); return null; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
wig2.QueueWorkItem(
|
||||||
|
delegate(object state) { Thread.Sleep(500); Interlocked.Increment(ref counter2); return null; }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (counter1 < 3)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
wig1.Cancel(true);
|
||||||
|
|
||||||
|
stp.WaitForIdle();
|
||||||
|
|
||||||
|
Assert.AreEqual(3, counter1, "Cancelled WIG1");
|
||||||
|
Assert.AreEqual(3, counter2, "Normal WIG2");
|
||||||
|
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
private int _counter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void WorkItemCanceling()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
// It just to show how to use the work item canceling feature
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
||||||
|
|
||||||
|
// Queue a work item that will occupy the thread in the pool
|
||||||
|
IWorkItemResult wir1 =
|
||||||
|
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
|
||||||
|
// Queue another work item that will wait for the first to complete
|
||||||
|
IWorkItemResult wir2 =
|
||||||
|
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
|
||||||
|
// Wait a while for the thread pool to start executing the first work item
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// The first work item cannot be canceled since it is currently executing
|
||||||
|
if (!wir1.Cancel())
|
||||||
|
{
|
||||||
|
// Cancel the second work item while it still in the queue
|
||||||
|
if (wir2.Cancel())
|
||||||
|
{
|
||||||
|
// Retreiving result of a canceled work item throws WorkItemCancelException exception
|
||||||
|
wir2.GetResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void WorkItemCancelingAndInUseWorkerThreads()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 10);
|
||||||
|
|
||||||
|
IWorkItemResult [] wirs = new IWorkItemResult[100];
|
||||||
|
for(int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait a while for the thread pool to start executing the first work item
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
for(int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
wirs[i].Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.WaitForIdle(2000);
|
||||||
|
|
||||||
|
int inUseThreads = smartThreadPool.InUseThreads;
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.AreEqual(0, inUseThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check within the work item if it was cancelled
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void SampleIfWorkItemCancelled()
|
||||||
|
{
|
||||||
|
_counter = 0;
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.StartSuspended = true;
|
||||||
|
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(stpStartInfo);
|
||||||
|
|
||||||
|
IWorkItemResult[] wirs = new IWorkItemResult[100];
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancelledWorkItem), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; ++i)
|
||||||
|
{
|
||||||
|
wirs[i].Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.Start();
|
||||||
|
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.AreEqual(50, _counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item into the STP
|
||||||
|
/// 4. Cancel the work item
|
||||||
|
/// 5. Work item doesn't check for cancel
|
||||||
|
/// 6. Work item quits
|
||||||
|
/// 7. Make sure the work item result is ok, and not an exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestWorkItemCancelledWorkItemOK()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// Since the work item didn't sample the cancel, it was not aware that it
|
||||||
|
// was canceled. Therefore the result should be what the work item returned
|
||||||
|
// and not the cancel exeception
|
||||||
|
int result = (int)wir.GetResult(0, false);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Create WIG
|
||||||
|
/// 3. Queue work item into the WIG
|
||||||
|
/// 4. Cancel the work items in the WIG
|
||||||
|
/// 5. Work item doesn't check for cancel
|
||||||
|
/// 6. Work item quits
|
||||||
|
/// 7. Make sure the work item result is ok, and not an exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestWIGCancelledWorkItemOK()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
wig.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// Since the work item didn't sample the cancel, it was not aware that it
|
||||||
|
// was canceled. Therefore the result should be what the work item returned
|
||||||
|
// and not the cancel exeception
|
||||||
|
int result = (int)wir.GetResult(0, false);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item into the STP
|
||||||
|
/// 3. Cancel the work items in the STP
|
||||||
|
/// 4. Work item doesn't check for cancel
|
||||||
|
/// 5. Work item quits
|
||||||
|
/// 6. Make sure the work item result is ok, and not an exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestSTPCancelledWorkItemOK()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoWaitForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
smartThreadPool.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// Since the work item didn't sample the cancel, it was not aware that it
|
||||||
|
// was canceled. Therefore the result should be what the work item returned
|
||||||
|
// and not the cancel exeception
|
||||||
|
int result = (int)wir.GetResult(0, false);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Queue work item
|
||||||
|
/// 3. Cancel the work item
|
||||||
|
/// 4. Work item checks the cancel and quits
|
||||||
|
/// 5. Make sure the work item result throws exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void TestWorkItemCanceledWorkItemCancelException()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
wir.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// The work item samples the cancel, therefore it is aware that it
|
||||||
|
// was canceled. Using the GetResult should throw the cancel exeception
|
||||||
|
wir.GetResult(0, false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 2. Create WIG
|
||||||
|
/// 3. Queue work item into the WIG
|
||||||
|
/// 4. Cancel the work items in the WIG
|
||||||
|
/// 5. Work item checks the cancel and quits
|
||||||
|
/// 6. Make sure the work item result throws exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void TestWIGCancelledWorkItemCancelException()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = wig.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
wig.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// The work item samples the cancel, therefore it is aware that it
|
||||||
|
// was canceled. Using the GetResult should throw the cancel exeception
|
||||||
|
wir.GetResult(0, false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1. Create STP
|
||||||
|
/// 3. Queue work item into the STP
|
||||||
|
/// 4. Cancel the work items in the STP
|
||||||
|
/// 5. Work item checks the cancel and quits
|
||||||
|
/// 6. Make sure the work item result throws exception
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemCancelException))]
|
||||||
|
public void TestSTPCancelledWorkItemCancelException()
|
||||||
|
{
|
||||||
|
// Create a SmartThreadPool with only one thread.
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
AutoResetEvent start = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
// Queue the work item
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoCheckForCancel), start);
|
||||||
|
|
||||||
|
// Wait for it to start executing
|
||||||
|
bool success = start.WaitOne(3000, false);
|
||||||
|
|
||||||
|
// Make sure it was started
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
// Cancel the work item
|
||||||
|
smartThreadPool.Cancel();
|
||||||
|
|
||||||
|
// Let it complete
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Wait for the work item to complete
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check the work item's result
|
||||||
|
// The work item started running after it was start its execution.
|
||||||
|
// The work item samples the cancel, therefore it is aware that it
|
||||||
|
// was canceled. Using the GetResult should throw the cancel exeception
|
||||||
|
wir.GetResult(0, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoCheckForCancelledWorkItem(object state)
|
||||||
|
{
|
||||||
|
if (!SmartThreadPool.IsWorkItemCanceled)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoWaitForCancel(object state)
|
||||||
|
{
|
||||||
|
AutoResetEvent start = state as AutoResetEvent;
|
||||||
|
|
||||||
|
// Signal the test that the work item started
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Let the test run (or else the next line may reset the signaled event)
|
||||||
|
Thread.Sleep(10);
|
||||||
|
|
||||||
|
// Wait for the test to cancel the work item
|
||||||
|
start.WaitOne();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoCheckForCancel(object state)
|
||||||
|
{
|
||||||
|
AutoResetEvent start = state as AutoResetEvent;
|
||||||
|
|
||||||
|
// Signal the test that the work item started
|
||||||
|
start.Set();
|
||||||
|
|
||||||
|
// Let the test run (or else the next line may reset the signaled event)
|
||||||
|
Thread.Sleep(10);
|
||||||
|
|
||||||
|
// Wait for the test to cancel the work item
|
||||||
|
start.WaitOne();
|
||||||
|
|
||||||
|
// Sample if the work item was cancelled
|
||||||
|
bool cancelled = SmartThreadPool.IsWorkItemCanceled;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestConcurrencyChanges.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestConcurrencyChanges")]
|
||||||
|
public class TestConcurrencyChanges
|
||||||
|
{
|
||||||
|
public TestConcurrencyChanges()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example of waiting for idle
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestMaxThreadsChange()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(1 * 1000, 1, 0);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
smartThreadPool.QueueWorkItem(
|
||||||
|
new WorkItemCallback(this.DoSomeWork),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 1, 1 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MaxThreads = 5;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 5, 2 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MaxThreads = 25;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 25, 4 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MaxThreads = 10;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 10, 10 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMinThreadsChange()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(1 * 1000, 25, 0);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
success = WaitForMinThreadsValue(smartThreadPool, 0, 1 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MinThreads = 5;
|
||||||
|
success = WaitForMinThreadsValue(smartThreadPool, 5, 2 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MinThreads = 25;
|
||||||
|
success = WaitForMinThreadsValue(smartThreadPool, 25, 4 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.MinThreads = 10;
|
||||||
|
success = WaitForMinThreadsValue(smartThreadPool, 10, 10 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example of waiting for idle
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestConcurrencyChange()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10 * 1000, 1, 0);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
smartThreadPool.QueueWorkItem(
|
||||||
|
new WorkItemCallback(this.DoSomeWork),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.Concurrency = 1;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 1, 1 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Concurrency = 5;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 5, 2 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Concurrency = 25;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 25, 4 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Concurrency = 10;
|
||||||
|
success = WaitForMaxThreadsValue(smartThreadPool, 10, 10 * 1000);
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool WaitForMaxThreadsValue(SmartThreadPool smartThreadPool, int maxThreadsCount, int timeout)
|
||||||
|
{
|
||||||
|
DateTime end = DateTime.Now + new TimeSpan(0, 0, 0, 0, timeout);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
while(DateTime.Now <= end && !success)
|
||||||
|
{
|
||||||
|
success = (smartThreadPool.InUseThreads == maxThreadsCount);
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool WaitForMinThreadsValue(SmartThreadPool smartThreadPool, int minThreadsCount, int timeout)
|
||||||
|
{
|
||||||
|
DateTime end = DateTime.Now + new TimeSpan(0, 0, 0, 0, timeout);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
while (DateTime.Now <= end && !success)
|
||||||
|
{
|
||||||
|
success = (smartThreadPool.ActiveThreads == minThreadsCount);
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int x = 0;
|
||||||
|
private object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(Interlocked.Increment(ref x));
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
using System;
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace STPTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestFalseFillStateWithArgs.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestFalseFillStateWithArgs")]
|
||||||
|
public class TestFalseFillStateWithArgs
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
_wig = _stp.CreateWorkItemsGroup(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.WaitForIdle();
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPActionT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action0);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPActionT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action1, 17);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPActionT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action2, 'a', "bla bla");
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPActionT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action3, true, chars, obj);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPActionT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action4, long.MinValue, p, ip, guid);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPFuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _stp.QueueWorkItem(new Func<int>(Func0));
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPFuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _stp.QueueWorkItem(new Func<int, bool>(Func1), 17);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPFuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _stp.QueueWorkItem(new Func<char, string, string>(Func2), 'a', "bla bla");
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPFuncT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult<char> wir = _stp.QueueWorkItem(new Func<bool, char[], object, char>(Func3), true, chars, obj);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void STPFuncT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult<IPAddress> wir = _stp.QueueWorkItem(new Func<long, IntPtr, IPAddress, Guid, IPAddress>(Func4), long.MinValue, p, ip, guid);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGActionT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action0);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGActionT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action1, 17);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGActionT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action2, 'a', "bla bla");
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGActionT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action3, true, chars, obj);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGActionT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action4, long.MinValue, p, ip, guid);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGFuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _wig.QueueWorkItem(new Func<int>(Func0));
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGFuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _wig.QueueWorkItem(new Func<int, bool>(Func1), 17);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGFuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _wig.QueueWorkItem(new Func<char, string, string>(Func2), 'a', "bla bla");
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGFuncT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult<char> wir = _wig.QueueWorkItem(new Func<bool, char[], object, char>(Func3), true, chars, obj);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WIGFuncT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult<IPAddress> wir = _wig.QueueWorkItem(new Func<long, IntPtr, IPAddress, Guid, IPAddress>(Func4), long.MinValue, p, ip, guid);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Action0()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action1(int p1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action2(char p1, string p2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Func0()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Func1(int p1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Func2(char p1, string p2)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Func3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
return 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPAddress Func4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
return IPAddress.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
using System;
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace STPTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestFillStateWithArgs.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestFillStateWithArgs")]
|
||||||
|
public class TestFillStateWithArgs
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.FillStateWithArgs = true;
|
||||||
|
_stp = new SmartThreadPool(stpStartInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.WaitForIdle();
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action0);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action1, 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action2, 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] {'a', 'b'};
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action3, true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action4, long.MinValue, p, ip, guid);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _stp.QueueWorkItem(new Func<int>(Func0));
|
||||||
|
Assert.AreEqual(wir.State, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _stp.QueueWorkItem(new Func<int, bool>(Func1), 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _stp.QueueWorkItem(new Func<char, string, string>(Func2), 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult<char> wir = _stp.QueueWorkItem(new Func<bool, char[], object, char>(Func3), true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult<IPAddress> wir = _stp.QueueWorkItem(new Func<long, IntPtr, IPAddress, Guid, IPAddress>(Func4), long.MinValue, p, ip, guid);
|
||||||
|
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Action0()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action1(int p1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action2(char p1, string p2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action3(bool p1, char [] p2, object p3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Func0()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Func1(int p1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Func2(char p1, string p2)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Func3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
return 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPAddress Func4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
return IPAddress.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace STPTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestCancel.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestFuncT")]
|
||||||
|
public class TestFuncT
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void FuncT()
|
||||||
|
{
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
IWorkItemResult<int> wir =
|
||||||
|
stp.QueueWorkItem(new Func<int, int>(f), 1);
|
||||||
|
|
||||||
|
int y = wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(y, 2);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
wir.GetResult();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stp.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int f(int x)
|
||||||
|
{
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestCancel.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestFuncT")]
|
||||||
|
public class TestFuncT
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _stp.QueueWorkItem(new Func<int>(MaxInt));
|
||||||
|
|
||||||
|
int result = wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(result, int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _stp.QueueWorkItem(new Func<bool, bool>(Not), true);
|
||||||
|
|
||||||
|
bool result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _stp.QueueWorkItem(new Func<string, string, string>(string.Concat), "ABC", "xyz");
|
||||||
|
|
||||||
|
string result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, "ABCxyz");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT3()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _stp.QueueWorkItem(new Func<string, int, int, string>(Substring), "ABCDEF", 1, 2);
|
||||||
|
|
||||||
|
string result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, "BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT4()
|
||||||
|
{
|
||||||
|
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
|
||||||
|
IWorkItemResult<int[]> wir = _stp.QueueWorkItem(new Func<int[], int, int, int, int[]>(Subarray), numbers, 1, 2, 3);
|
||||||
|
|
||||||
|
int[] result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, new int[] { 2, 3, 2, 3, 2, 3, });
|
||||||
|
}
|
||||||
|
|
||||||
|
private int MaxInt()
|
||||||
|
{
|
||||||
|
return int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Not(bool flag)
|
||||||
|
{
|
||||||
|
return !flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Substring(string s, int startIndex, int length)
|
||||||
|
{
|
||||||
|
return s.Substring(startIndex, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] Subarray(int[] numbers, int startIndex, int length, int repeat)
|
||||||
|
{
|
||||||
|
int[] result = new int[length * repeat];
|
||||||
|
for (int i = 0; i < repeat; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
result[i * length + j] = numbers[startIndex + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,12 +42,11 @@ namespace SmartThreadPoolTests
|
|||||||
/// Example of how to queue a work item and then wait on a timeout for the result.
|
/// Example of how to queue a work item and then wait on a timeout for the result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemTimeoutException))]
|
||||||
public void Timeout()
|
public void Timeout()
|
||||||
{
|
{
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
IWorkItemResult wir =
|
IWorkItemResult wir =
|
||||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
|
||||||
@@ -55,74 +54,23 @@ namespace SmartThreadPoolTests
|
|||||||
{
|
{
|
||||||
wir.GetResult(500, true);
|
wir.GetResult(500, true);
|
||||||
}
|
}
|
||||||
catch (WorkItemTimeoutException)
|
finally
|
||||||
{
|
{
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
Assert.IsTrue(success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void WorkItemCanceling()
|
|
||||||
{
|
|
||||||
// Create a SmartThreadPool with only one thread.
|
|
||||||
// It just to show how to use the work item canceling feature
|
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Queue a work item that will occupy the thread in the pool
|
|
||||||
IWorkItemResult wir1 =
|
|
||||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Queue another work item that will wait for the first to complete
|
|
||||||
IWorkItemResult wir2 =
|
|
||||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Wait a while for the thread pool to start executing the first work item
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
// The first work item cannot be canceled since it is currently executing
|
|
||||||
if (!wir1.Cancel())
|
|
||||||
{
|
|
||||||
// Cancel the second work item while it still in the queue
|
|
||||||
if (wir2.Cancel())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Retreiving result of a canceled work item throws an exception
|
|
||||||
wir2.GetResult();
|
|
||||||
}
|
|
||||||
catch (WorkItemCancelException)
|
|
||||||
{
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
|
||||||
|
|
||||||
Assert.IsTrue(success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Example of how to interrupt the waiting for a work item to complete.
|
/// Example of how to interrupt the waiting for a work item to complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
|
[ExpectedException(typeof(WorkItemTimeoutException))]
|
||||||
public void WorkItemWaitCanceling()
|
public void WorkItemWaitCanceling()
|
||||||
{
|
{
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
ManualResetEvent cancelWaitHandle = new ManualResetEvent(false);
|
ManualResetEvent cancelWaitHandle = new ManualResetEvent(false);
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Queue a work item that will occupy the thread in the pool
|
// Queue a work item that will occupy the thread in the pool
|
||||||
IWorkItemResult wir1 =
|
IWorkItemResult wir1 =
|
||||||
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
@@ -135,52 +83,12 @@ namespace SmartThreadPoolTests
|
|||||||
{
|
{
|
||||||
wir1.GetResult(System.Threading.Timeout.Infinite, true, cancelWaitHandle);
|
wir1.GetResult(System.Threading.Timeout.Infinite, true, cancelWaitHandle);
|
||||||
}
|
}
|
||||||
catch (WorkItemTimeoutException)
|
finally
|
||||||
{
|
{
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
Assert.IsTrue(success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void WorkItemCancelingAndInUseWorkerThreads()
|
|
||||||
{
|
|
||||||
// Create a SmartThreadPool with only one thread.
|
|
||||||
// It just to show how to use the work item canceling feature
|
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 10);
|
|
||||||
|
|
||||||
IWorkItemResult [] wirs = new IWorkItemResult[100];
|
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
wirs[i] = smartThreadPool.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Wait a while for the thread pool to start executing the first work item
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
for(int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
wirs[i].Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.WaitForIdle(2000);
|
|
||||||
|
|
||||||
int inUseThreads = smartThreadPool.InUseThreads;
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
|
||||||
|
|
||||||
Assert.AreEqual(0, inUseThreads);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private object DoSomeWork(object state)
|
private object DoSomeWork(object state)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
@@ -194,5 +102,6 @@ namespace SmartThreadPoolTests
|
|||||||
cancelWaitHandle.Set();
|
cancelWaitHandle.Set();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,5 +228,73 @@ namespace SmartThreadPoolTests
|
|||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WaitAllT()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
IWorkItemResult<int>[] wirs = new IWorkItemResult<int>[5];
|
||||||
|
|
||||||
|
for (int i = 0; i < wirs.Length; ++i)
|
||||||
|
{
|
||||||
|
wirs[i] = smartThreadPool.QueueWorkItem(new Func<int, int, int>(Math.Min), i, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmartThreadPool.WaitAll(wirs);
|
||||||
|
|
||||||
|
for (int i = 0; i < wirs.Length; ++i)
|
||||||
|
{
|
||||||
|
if (!wirs[i].IsCompleted)
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = wirs[i].GetResult();
|
||||||
|
if (i != result)
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WaitAnyT()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
IWorkItemResult<int>[] wirs = new IWorkItemResult<int>[5];
|
||||||
|
|
||||||
|
for (int i = 0; i < wirs.Length; ++i)
|
||||||
|
{
|
||||||
|
wirs[i] = smartThreadPool.QueueWorkItem(new Func<int, int, int>(Math.Max), i, i - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = SmartThreadPool.WaitAny(wirs);
|
||||||
|
|
||||||
|
if (wirs[index].IsCompleted)
|
||||||
|
{
|
||||||
|
int result = wirs[index].GetResult();
|
||||||
|
if (index == result)
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests for QueueWorkItem.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestQueueWorkItem")]
|
||||||
|
public class TestQueueWorkItem
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCall()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCall(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallPrio(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStat()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStat(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPrio(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPost()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPost(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPrio(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPflg()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPflg(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPflgPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPflgPrio(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemInfoCall()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemInfoCall(_stp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemInfoCallStat()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemInfoCallStat(_stp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace SmartThreadPoolTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestThreadsCreate")]
|
||||||
|
public class TestThreadsCreate
|
||||||
|
{
|
||||||
|
private bool _initSuccess;
|
||||||
|
private bool _workItemSuccess;
|
||||||
|
private bool _termSuccess;
|
||||||
|
|
||||||
|
private void ClearResults()
|
||||||
|
{
|
||||||
|
_initSuccess = false;
|
||||||
|
_workItemSuccess = false;
|
||||||
|
_termSuccess = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestThreadsEvents()
|
||||||
|
{
|
||||||
|
ClearResults();
|
||||||
|
|
||||||
|
SmartThreadPool stp = new SmartThreadPool();
|
||||||
|
|
||||||
|
stp.OnThreadInitialization += new ThreadInitializationHandler(OnInitialization);
|
||||||
|
stp.OnThreadTermination += new ThreadTerminationHandler(OnTermination);
|
||||||
|
|
||||||
|
stp.QueueWorkItem(new WorkItemCallback(DoSomeWork), null);
|
||||||
|
|
||||||
|
stp.WaitForIdle();
|
||||||
|
stp.Shutdown();
|
||||||
|
|
||||||
|
Assert.IsTrue(_initSuccess);
|
||||||
|
Assert.IsTrue(_workItemSuccess);
|
||||||
|
Assert.IsTrue(_termSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnInitialization()
|
||||||
|
{
|
||||||
|
ThreadContextState.Current.Counter = 1234;
|
||||||
|
_initSuccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
int counter = ThreadContextState.Current.Counter;
|
||||||
|
_workItemSuccess = (1234 == counter);
|
||||||
|
|
||||||
|
ThreadContextState.Current.Counter = 1111;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnTermination()
|
||||||
|
{
|
||||||
|
int counter = ThreadContextState.Current.Counter;
|
||||||
|
_termSuccess = (1111 == counter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ThreadContextState
|
||||||
|
{
|
||||||
|
// Each thread will have its own ThreadContextState object
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ThreadContextState _threadContextState;
|
||||||
|
|
||||||
|
private int _counter = 0;
|
||||||
|
|
||||||
|
public int Counter
|
||||||
|
{
|
||||||
|
get { return _counter; }
|
||||||
|
set { _counter = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static member so it can be used anywhere in code of the work item method
|
||||||
|
public static ThreadContextState Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// If the _threadContextState is null then it was not yet initialized
|
||||||
|
// for this thread.
|
||||||
|
if (null == _threadContextState)
|
||||||
|
{
|
||||||
|
// Create a ThreadContextState object
|
||||||
|
_threadContextState = new ThreadContextState();
|
||||||
|
}
|
||||||
|
return _threadContextState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestCancel.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestWIGActionT")]
|
||||||
|
public class TestWIGActionT
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig;
|
||||||
|
private object _result;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
_wig = _stp.CreateWorkItemsGroup(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT0()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(MaxInt);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT1()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Not, true);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT2()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Concat, "ABC", "xyz");
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, "ABCxyz");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT3()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Substring, "ABCDEF", 1, 2);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, "BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT4()
|
||||||
|
{
|
||||||
|
_result = null;
|
||||||
|
|
||||||
|
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Subarray, numbers, 1, 2, 3);
|
||||||
|
|
||||||
|
wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(_result, new int[] { 2, 3, 2, 3, 2, 3, });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MaxInt()
|
||||||
|
{
|
||||||
|
_result = int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Not(bool flag)
|
||||||
|
{
|
||||||
|
_result = !flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Concat(string s1, string s2)
|
||||||
|
{
|
||||||
|
_result = s1 + s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Substring(string s, int startIndex, int length)
|
||||||
|
{
|
||||||
|
_result = s.Substring(startIndex, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Subarray(int[] numbers, int startIndex, int length, int repeat)
|
||||||
|
{
|
||||||
|
int[] result = new int[length * repeat];
|
||||||
|
for (int i = 0; i < repeat; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
result[i * length + j] = numbers[startIndex + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ using NUnit.Framework;
|
|||||||
|
|
||||||
using Amib.Threading;
|
using Amib.Threading;
|
||||||
|
|
||||||
namespace SmartThreadPoolTests
|
namespace WorkItemsGroupTests
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for TestWIGConcurrency.
|
/// Summary description for TestWIGConcurrency.
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestWIGConcurrencyChanges.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestWIGConcurrencyChanges")]
|
||||||
|
public class TestWIGConcurrencyChanges
|
||||||
|
{
|
||||||
|
public TestWIGConcurrencyChanges()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example of waiting for idle
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestWIGConcurrencyChange1WIG()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1, 0);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
IWorkItemsGroup wig = smartThreadPool.CreateWorkItemsGroup(1);
|
||||||
|
wig.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig.Concurrency = 2;
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(2 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
ResumeSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
wig.Concurrency = 1;
|
||||||
|
|
||||||
|
wig.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
ResumeSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example of waiting for idle
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestWIGConcurrencyChange2WIGs()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10 * 1000, 2, 0);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
IWorkItemsGroup wig1 = smartThreadPool.CreateWorkItemsGroup(1);
|
||||||
|
IWorkItemsGroup wig2 = smartThreadPool.CreateWorkItemsGroup(1);
|
||||||
|
|
||||||
|
wig1.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig2.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(2 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig1.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(2 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig2.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(2 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig1.Concurrency = 2;
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(3 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig2.Concurrency = 2;
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(4 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
ResumeSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
PauseSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
wig1.Concurrency = 1;
|
||||||
|
|
||||||
|
wig1.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(1 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
wig2.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
||||||
|
Assert.IsTrue(2 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
ResumeSTP(smartThreadPool);
|
||||||
|
Thread.Sleep(100);
|
||||||
|
Assert.IsTrue(0 == smartThreadPool.WaitingCallbacks);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PauseSTP(SmartThreadPool stp)
|
||||||
|
{
|
||||||
|
_pauseSTP.Reset();
|
||||||
|
stp.QueueWorkItem(
|
||||||
|
new WorkItemCallback(this.DoPauseSTP),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResumeSTP(SmartThreadPool stp)
|
||||||
|
{
|
||||||
|
_pauseSTP.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ManualResetEvent _pauseSTP = new ManualResetEvent(false);
|
||||||
|
private object DoPauseSTP(object state)
|
||||||
|
{
|
||||||
|
_pauseSTP.WaitOne();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// <summary>
|
||||||
|
/// Example of waiting for idle
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void WaitForIdle()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
for(int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
smartThreadPool.QueueWorkItem(
|
||||||
|
new WorkItemCallback(this.DoSomeWork),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
success = !smartThreadPool.WaitForIdle(3500);
|
||||||
|
success = success && smartThreadPool.WaitForIdle(1000);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.IsTrue(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WaitForIdleOnWrongThread()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||||
|
|
||||||
|
IWorkItemResult wir = smartThreadPool.QueueWorkItem(
|
||||||
|
new WorkItemCallback(this.DoWaitForIdle),
|
||||||
|
smartThreadPool);
|
||||||
|
|
||||||
|
Exception e;
|
||||||
|
wir.GetResult(out e);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
|
||||||
|
Assert.IsTrue(e is NotSupportedException);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int x = 0;
|
||||||
|
private object DoSomeWork(object state)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(Interlocked.Increment(ref x));
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoWaitForIdle(object state)
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = state as SmartThreadPool;
|
||||||
|
smartThreadPool.WaitForIdle();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
using System;
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace STPTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestWIGFillStateWithArgs.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestWIGFillStateWithArgs")]
|
||||||
|
public class TestWIGFillStateWithArgs
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
|
||||||
|
WIGStartInfo wigStartInfo = new WIGStartInfo();
|
||||||
|
wigStartInfo.FillStateWithArgs = true;
|
||||||
|
_wig = _stp.CreateWorkItemsGroup(10, wigStartInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.WaitForIdle();
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action0);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action1, 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action2, 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action3, true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult wir = _wig.QueueWorkItem(Action4, long.MinValue, p, ip, guid);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _wig.QueueWorkItem(new Func<int>(Func0));
|
||||||
|
Assert.AreEqual(wir.State, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _wig.QueueWorkItem(new Func<int, bool>(Func1), 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _wig.QueueWorkItem(new Func<char, string, string>(Func2), 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult<char> wir = _wig.QueueWorkItem(new Func<bool, char[], object, char>(Func3), true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult<IPAddress> wir = _wig.QueueWorkItem(new Func<long, IntPtr, IPAddress, Guid, IPAddress>(Func4), long.MinValue, p, ip, guid);
|
||||||
|
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Action0()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action1(int p1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action2(char p1, string p2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Func0()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Func1(int p1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Func2(char p1, string p2)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Func3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
return 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPAddress Func4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
return IPAddress.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
using System;
|
||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace STPTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for TestFillStateWithParams.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestFillStateWithParams")]
|
||||||
|
public class TestFillStateWithParams
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.FillStateWithParams = true;
|
||||||
|
_stp = new SmartThreadPool(stpStartInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.WaitForIdle();
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action0);
|
||||||
|
Assert.IsNull(wir.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action1, 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action2, 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] {'a', 'b'};
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action3, true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ActionT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult wir = _stp.QueueWorkItem(Action4, long.MinValue, p, ip, guid);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _stp.QueueWorkItem(new Func<int>(Func0));
|
||||||
|
Assert.AreEqual(wir.State, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _stp.QueueWorkItem(new Func<int, bool>(Func1), 17);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 1);
|
||||||
|
Assert.AreEqual(args[0], 17);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _stp.QueueWorkItem(new Func<char, string, string>(Func2), 'a', "bla bla");
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 2);
|
||||||
|
Assert.AreEqual(args[0], 'a');
|
||||||
|
Assert.AreEqual(args[1], "bla bla");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT3()
|
||||||
|
{
|
||||||
|
char[] chars = new char[] { 'a', 'b' };
|
||||||
|
object obj = new object();
|
||||||
|
|
||||||
|
IWorkItemResult<char> wir = _stp.QueueWorkItem(new Func<bool, char[], object, char>(Func3), true, chars, obj);
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 3);
|
||||||
|
Assert.AreEqual(args[0], true);
|
||||||
|
Assert.AreEqual(args[1], chars);
|
||||||
|
Assert.AreEqual(args[2], obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT4()
|
||||||
|
{
|
||||||
|
IntPtr p = new IntPtr(int.MaxValue);
|
||||||
|
Guid guid = Guid.NewGuid();
|
||||||
|
|
||||||
|
IPAddress ip = IPAddress.Parse("1.2.3.4");
|
||||||
|
IWorkItemResult<IPAddress> wir = _stp.QueueWorkItem(new Func<long, IntPtr, IPAddress, Guid, IPAddress>(Func4), long.MinValue, p, ip, guid);
|
||||||
|
|
||||||
|
object[] args = wir.State as object[];
|
||||||
|
|
||||||
|
Assert.IsNotNull(args);
|
||||||
|
Assert.AreEqual(args.Length, 4);
|
||||||
|
Assert.AreEqual(args[0], long.MinValue);
|
||||||
|
Assert.AreEqual(args[1], p);
|
||||||
|
Assert.AreEqual(args[2], ip);
|
||||||
|
Assert.AreEqual(args[3], guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Action0()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action1(int p1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action2(char p1, string p2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action3(bool p1, char [] p2, object p3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Action4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private int Func0()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Func1(int p1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Func2(char p1, string p2)
|
||||||
|
{
|
||||||
|
return "value";
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Func3(bool p1, char[] p2, object p3)
|
||||||
|
{
|
||||||
|
return 'z';
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPAddress Func4(long p1, IntPtr p2, IPAddress p3, Guid p4)
|
||||||
|
{
|
||||||
|
return IPAddress.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
using Amib.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestWIGFuncT")]
|
||||||
|
public class TestWIGFuncT
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
_wig = _stp.CreateWorkItemsGroup(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT0()
|
||||||
|
{
|
||||||
|
IWorkItemResult<int> wir = _wig.QueueWorkItem(new Func<int>(MaxInt));
|
||||||
|
|
||||||
|
int result = wir.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(result, int.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT1()
|
||||||
|
{
|
||||||
|
IWorkItemResult<bool> wir = _wig.QueueWorkItem(new Func<bool, bool>(Not), true);
|
||||||
|
|
||||||
|
bool result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT2()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _wig.QueueWorkItem(new Func<string, string, string>(string.Concat), "ABC", "xyz");
|
||||||
|
|
||||||
|
string result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, "ABCxyz");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT3()
|
||||||
|
{
|
||||||
|
IWorkItemResult<string> wir = _wig.QueueWorkItem(new Func<string, int, int, string>(Substring), "ABCDEF", 1, 2);
|
||||||
|
|
||||||
|
string result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, "BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncT4()
|
||||||
|
{
|
||||||
|
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||||
|
|
||||||
|
IWorkItemResult<int[]> wir = _wig.QueueWorkItem(new Func<int[], int, int, int, int[]>(Subarray), numbers, 1, 2, 3);
|
||||||
|
|
||||||
|
int[] result = wir.Result;
|
||||||
|
|
||||||
|
Assert.AreEqual(result, new int[] { 2, 3, 2, 3, 2, 3, });
|
||||||
|
}
|
||||||
|
|
||||||
|
private int MaxInt()
|
||||||
|
{
|
||||||
|
return int.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Not(bool flag)
|
||||||
|
{
|
||||||
|
return !flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Substring(string s, int startIndex, int length)
|
||||||
|
{
|
||||||
|
return s.Substring(startIndex, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] Subarray(int[] numbers, int startIndex, int length, int repeat)
|
||||||
|
{
|
||||||
|
int[] result = new int[length * repeat];
|
||||||
|
for (int i = 0; i < repeat; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
result[i * length + j] = numbers[startIndex + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,53 +67,6 @@ namespace WorkItemsGroupTests
|
|||||||
Assert.IsTrue(success);
|
Assert.IsTrue(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void WorkItemCanceling()
|
|
||||||
{
|
|
||||||
// Create a SmartThreadPool with only one thread.
|
|
||||||
// It just to show how to use the work item canceling feature
|
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
|
||||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Queue a work item that will occupy the thread in the pool
|
|
||||||
IWorkItemResult wir1 =
|
|
||||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Queue another work item that will wait for the first to complete
|
|
||||||
IWorkItemResult wir2 =
|
|
||||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Wait a while for the thread pool to start executing the first work item
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
// The first work item cannot be canceled since it is currently executing
|
|
||||||
if (!wir1.Cancel())
|
|
||||||
{
|
|
||||||
// Cancel the second work item while it still in the queue
|
|
||||||
if (wir2.Cancel())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Retreiving result of a canceled work item throws an exception
|
|
||||||
wir2.GetResult();
|
|
||||||
}
|
|
||||||
catch (WorkItemCancelException)
|
|
||||||
{
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
|
||||||
|
|
||||||
Assert.IsTrue(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Example of how to interrupt the waiting for a work item to complete.
|
/// Example of how to interrupt the waiting for a work item to complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
using Amib.Threading;
|
||||||
|
using SmartThreadPoolTests;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tests for QueueWorkItem.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
[Category("TestQueueWorkItem")]
|
||||||
|
public class TestQueueWorkItem
|
||||||
|
{
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
_stp = new SmartThreadPool();
|
||||||
|
_wig = _stp.CreateWorkItemsGroup(SmartThreadPool.DefaultMaxWorkerThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void Fini()
|
||||||
|
{
|
||||||
|
_stp.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCall()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCall(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallPrio(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStat()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStat(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPrio(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPost()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPost(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPrio(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPflg()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPflg(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemCallStatPostPflgPrio()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemCallStatPostPflgPrio(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemInfoCall()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemInfoCall(_wig);
|
||||||
|
}
|
||||||
|
|
||||||
|
//IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
|
[Test]
|
||||||
|
public void TestQueueWorkItemInfoCallStat()
|
||||||
|
{
|
||||||
|
QueueWorkItemHelper.TestQueueWorkItemInfoCallStat(_wig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,15 +29,17 @@ namespace WorkItemsGroupTests
|
|||||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
ManualResetEvent isRunning = new ManualResetEvent(false);
|
||||||
|
|
||||||
for(int i = 0; i < 100; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
workItemsGroup.QueueWorkItem(
|
workItemsGroup.QueueWorkItem(delegate { isRunning.WaitOne(); });
|
||||||
new WorkItemCallback(this.DoSomeWork),
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
success = !workItemsGroup.WaitForIdle(3500);
|
success = !workItemsGroup.WaitForIdle(1000);
|
||||||
|
|
||||||
|
isRunning.Set();
|
||||||
|
|
||||||
success = success && workItemsGroup.WaitForIdle(1000);
|
success = success && workItemsGroup.WaitForIdle(1000);
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
@@ -72,11 +74,11 @@ namespace WorkItemsGroupTests
|
|||||||
|
|
||||||
workItemsGroup1.QueueWorkItem(
|
workItemsGroup1.QueueWorkItem(
|
||||||
new WorkItemCallback(this.DoSomeWork),
|
new WorkItemCallback(this.DoSomeWork),
|
||||||
null);
|
1000);
|
||||||
|
|
||||||
workItemsGroup1.QueueWorkItem(
|
workItemsGroup1.QueueWorkItem(
|
||||||
new WorkItemCallback(this.DoSomeWork),
|
new WorkItemCallback(this.DoSomeWork),
|
||||||
null);
|
1000);
|
||||||
|
|
||||||
IWorkItemResult wir = workItemsGroup2.QueueWorkItem(
|
IWorkItemResult wir = workItemsGroup2.QueueWorkItem(
|
||||||
new WorkItemCallback(this.DoWaitForIdle),
|
new WorkItemCallback(this.DoWaitForIdle),
|
||||||
@@ -91,11 +93,16 @@ namespace WorkItemsGroupTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int x = 0;
|
private int _x = 0;
|
||||||
private object DoSomeWork(object state)
|
private object DoSomeWork(object state)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(Interlocked.Increment(ref x));
|
int sleepTime = (int)state;
|
||||||
Thread.Sleep(1000);
|
int newX = Interlocked.Increment(ref _x);
|
||||||
|
Console.WriteLine("{0}: Enter, newX = {1}", DateTime.Now.ToLongTimeString(), newX);
|
||||||
|
Console.WriteLine("{0}: Sleeping for {1} ms", DateTime.Now.ToLongTimeString(), sleepTime);
|
||||||
|
Thread.Sleep(sleepTime);
|
||||||
|
newX = Interlocked.Increment(ref _x);
|
||||||
|
Console.WriteLine("{0}: Leave, newX = {1}", DateTime.Now.ToLongTimeString(), newX);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,5 +112,52 @@ namespace WorkItemsGroupTests
|
|||||||
workItemsGroup.WaitForIdle();
|
workItemsGroup.WaitForIdle();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WaitForIdleWithCancel()
|
||||||
|
{
|
||||||
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10 * 1000, 1, 1);
|
||||||
|
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(2);
|
||||||
|
|
||||||
|
_x = 0;
|
||||||
|
|
||||||
|
IWorkItemResult wir1 = workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), 1000);
|
||||||
|
IWorkItemResult wir2 = workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), 1000);
|
||||||
|
IWorkItemResult wir3 = workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), 1000);
|
||||||
|
|
||||||
|
while (0 == _x)
|
||||||
|
{
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("{0}: Cancelling WIG", DateTime.Now.ToLongTimeString());
|
||||||
|
workItemsGroup.Cancel();
|
||||||
|
|
||||||
|
// At this point:
|
||||||
|
// The first work item is running
|
||||||
|
// The second work item is cancelled, but waits in the STP queue
|
||||||
|
// The third work item is cancelled.
|
||||||
|
|
||||||
|
Assert.AreEqual(1, _x);
|
||||||
|
|
||||||
|
Assert.IsTrue(wir2.IsCanceled);
|
||||||
|
|
||||||
|
Assert.IsTrue(wir3.IsCanceled);
|
||||||
|
|
||||||
|
// Make sure the workItemsGroup is still idle
|
||||||
|
Assert.IsFalse(workItemsGroup.IsIdle);
|
||||||
|
|
||||||
|
Console.WriteLine("{0}: Waiting for 1st result", DateTime.Now.ToLongTimeString());
|
||||||
|
wir1.GetResult();
|
||||||
|
|
||||||
|
Assert.AreEqual(2, _x);
|
||||||
|
|
||||||
|
bool isIdle = workItemsGroup.WaitForIdle(100);
|
||||||
|
|
||||||
|
Assert.IsTrue(isIdle);
|
||||||
|
|
||||||
|
smartThreadPool.Shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,15 +28,17 @@ namespace SmartThreadPoolTests
|
|||||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 25, 0);
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
ManualResetEvent isRunning = new ManualResetEvent(false);
|
||||||
|
|
||||||
for(int i = 0; i < 100; ++i)
|
for(int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
smartThreadPool.QueueWorkItem(
|
smartThreadPool.QueueWorkItem(delegate { isRunning.WaitOne(); });
|
||||||
new WorkItemCallback(this.DoSomeWork),
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
success = !smartThreadPool.WaitForIdle(3500);
|
success = !smartThreadPool.WaitForIdle(1000);
|
||||||
|
|
||||||
|
isRunning.Set();
|
||||||
|
|
||||||
success = success && smartThreadPool.WaitForIdle(1000);
|
success = success && smartThreadPool.WaitForIdle(1000);
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
smartThreadPool.Shutdown();
|
||||||
|
|||||||
@@ -70,53 +70,6 @@ namespace WorkItemsGroupTests
|
|||||||
Assert.IsTrue(success);
|
Assert.IsTrue(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Example of how to queue a work item and then cancel it while it is in the queue.
|
|
||||||
/// </summary>
|
|
||||||
[Test]
|
|
||||||
public void WorkItemCanceling()
|
|
||||||
{
|
|
||||||
// Create a SmartThreadPool with only one thread.
|
|
||||||
// It just to show how to use the work item canceling feature
|
|
||||||
SmartThreadPool smartThreadPool = new SmartThreadPool(10*1000, 1);
|
|
||||||
IWorkItemsGroup workItemsGroup = smartThreadPool.CreateWorkItemsGroup(int.MaxValue);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Queue a work item that will occupy the thread in the pool
|
|
||||||
IWorkItemResult wir1 =
|
|
||||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Queue another work item that will wait for the first to complete
|
|
||||||
IWorkItemResult wir2 =
|
|
||||||
workItemsGroup.QueueWorkItem(new WorkItemCallback(this.DoSomeWork), null);
|
|
||||||
|
|
||||||
// Wait a while for the thread pool to start executing the first work item
|
|
||||||
Thread.Sleep(100);
|
|
||||||
|
|
||||||
// The first work item cannot be canceled since it is currently executing
|
|
||||||
if (!wir1.Cancel())
|
|
||||||
{
|
|
||||||
// Cancel the second work item while it still in the queue
|
|
||||||
if (wir2.Cancel())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Retreiving result of a canceled work item throws an exception
|
|
||||||
wir2.GetResult();
|
|
||||||
}
|
|
||||||
catch (WorkItemCancelException)
|
|
||||||
{
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
smartThreadPool.Shutdown();
|
|
||||||
|
|
||||||
Assert.IsTrue(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Example of how to interrupt the waiting for a work item to complete.
|
/// Example of how to interrupt the waiting for a work item to complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+71
-17
@@ -1,14 +1,53 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
# Visual Studio 2005
|
# Visual Studio 2005
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartThreadPool", "SmartThreadPool\SmartThreadPool.csproj", "{8684FC56-A679-4E2E-8F96-E172FB062EB6}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartThreadPoolCE", "SmartThreadPool\SmartThreadPoolCE.csproj", "{D81DD596-C71F-4AC2-816C-63C19589E7E0}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmartThreadPool", "SmartThreadPool\SmartThreadPool.csproj", "{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPExamples", "STPExamples\STPExamples.csproj", "{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPExamples", "STPExamples\STPExamples.csproj", "{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPTests", "STPTests\STPTests.csproj", "{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPTests", "STPTests\STPTests.csproj", "{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}"
|
||||||
EndProject
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UsageControl", "UsageControl\UsageControl.csproj", "{C11A4561-CCB5-4C96-8DF2-B804031D89D8}"
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSmartThreadPool", "TestSmartThreadPool\TestSmartThreadPool.csproj", "{976DB12F-9198-4AD9-981A-1652615C9B0D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSmartThreadPool", "TestSmartThreadPool\TestSmartThreadPool.csproj", "{976DB12F-9198-4AD9-981A-1652615C9B0D}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UsageControl", "UsageControl\UsageControl.csproj", "{C11A4561-CCB5-4C96-8DF2-B804031D89D8}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkItemsGroupDemo", "WorkItemsGroupDemo\WorkItemsGroupDemo.csproj", "{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STPCEDemo", "STPCEDemo\STPCEDemo.csproj", "{356114BA-5F10-4DB6-9971-987CE11F765F}"
|
||||||
|
ProjectSection(WebsiteProperties) = preProject
|
||||||
|
Debug.AspNetCompiler.Debug = "True"
|
||||||
|
Release.AspNetCompiler.Debug = "False"
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -16,26 +55,41 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{8684FC56-A679-4E2E-8F96-E172FB062EB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{8684FC56-A679-4E2E-8F96-E172FB062EB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8684FC56-A679-4E2E-8F96-E172FB062EB6}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
{8684FC56-A679-4E2E-8F96-E172FB062EB6}.Release|Any CPU.Build.0 = Debug|Any CPU
|
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D81DD596-C71F-4AC2-816C-63C19589E7E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Release|Any CPU.Build.0 = Debug|Any CPU
|
{AE943A5A-7CFD-4E0D-BA51-FB763AAEA9A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Release|Any CPU.Build.0 = Debug|Any CPU
|
{6A3E4DBF-12AD-4636-ACB3-24B5172FAE03}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Release|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Release|Any CPU.ActiveCfg = Debug|Any CPU
|
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Release|Any CPU.Build.0 = Debug|Any CPU
|
{976DB12F-9198-4AD9-981A-1652615C9B0D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C11A4561-CCB5-4C96-8DF2-B804031D89D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{356114BA-5F10-4DB6-9971-987CE11F765F}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = 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("1.0.*")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
|
||||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
|
||||||
//
|
|
||||||
// Use the attributes below to control which key is used for signing.
|
|
||||||
//
|
|
||||||
// Notes:
|
|
||||||
// (*) If no key is specified, the assembly is not signed.
|
|
||||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
|
||||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
|
||||||
// a key.
|
|
||||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
|
||||||
// following processing occurs:
|
|
||||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
|
||||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
|
||||||
// in the KeyFile is installed into the CSP and used.
|
|
||||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
|
||||||
// When specifying the KeyFile, the location of the KeyFile should be
|
|
||||||
// relative to the project output directory which is
|
|
||||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
|
||||||
// located in the project directory, you would specify the AssemblyKeyFile
|
|
||||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
|
||||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
|
||||||
// documentation for more information on this.
|
|
||||||
//
|
|
||||||
[assembly: AssemblyDelaySign(false)]
|
|
||||||
[assembly: AssemblyKeyFile("")]
|
|
||||||
[assembly: AssemblyKeyName("")]
|
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
|
||||||
|
#if !(WindowsCE)
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -6,7 +9,7 @@ using System.Web;
|
|||||||
using System.Runtime.Remoting.Messaging;
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
|
||||||
|
|
||||||
namespace Amib.Threading
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
#region CallerThreadContext class
|
#region CallerThreadContext class
|
||||||
|
|
||||||
@@ -19,10 +22,10 @@ namespace Amib.Threading
|
|||||||
#region Prepare reflection information
|
#region Prepare reflection information
|
||||||
|
|
||||||
// Cached type information.
|
// Cached type information.
|
||||||
private static MethodInfo getLogicalCallContextMethodInfo =
|
private static readonly MethodInfo getLogicalCallContextMethodInfo =
|
||||||
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
private static MethodInfo setLogicalCallContextMethodInfo =
|
private static readonly MethodInfo setLogicalCallContextMethodInfo =
|
||||||
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
private static string HttpContextSlotName = GetHttpContextSlotName();
|
private static string HttpContextSlotName = GetHttpContextSlotName();
|
||||||
@@ -31,9 +34,11 @@ namespace Amib.Threading
|
|||||||
{
|
{
|
||||||
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
|
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
|
||||||
if( fi != null )
|
if (fi != null)
|
||||||
return (string)fi.GetValue(null);
|
{
|
||||||
else // Use the default "HttpContext" slot name
|
return (string) fi.GetValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
return "HttpContext";
|
return "HttpContext";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,8 +46,8 @@ namespace Amib.Threading
|
|||||||
|
|
||||||
#region Private fields
|
#region Private fields
|
||||||
|
|
||||||
private HttpContext _httpContext = null;
|
private HttpContext _httpContext;
|
||||||
private LogicalCallContext _callContext = null;
|
private LogicalCallContext _callContext;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -123,10 +128,11 @@ namespace Amib.Threading
|
|||||||
if (callerThreadContext._httpContext != null)
|
if (callerThreadContext._httpContext != null)
|
||||||
{
|
{
|
||||||
HttpContext.Current = callerThreadContext._httpContext;
|
HttpContext.Current = callerThreadContext._httpContext;
|
||||||
|
//CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#if (WindowsCE)
|
||||||
|
|
||||||
|
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 EventWaitHandle
|
||||||
|
{
|
||||||
|
#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
|
||||||
|
|
||||||
|
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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
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 (WindowsCE)
|
||||||
|
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 (WindowsCE)
|
||||||
|
ReplaceEventHandle(waitHandle, true, initialState);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return waitHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (WindowsCE)
|
||||||
|
|
||||||
|
/// <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,32 +1,82 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
#if !(WindowsCE)
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Amib.Threading
|
namespace Amib.Threading
|
||||||
{
|
{
|
||||||
#region Exceptions
|
#region Exceptions
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class WorkItemCancelException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemCancelException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemCancelException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemCancelException(string message, Exception e)
|
||||||
|
: base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class WorkItemTimeoutException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemTimeoutException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemTimeoutException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemTimeoutException(string message, Exception e)
|
||||||
|
: base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class WorkItemResultException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemResultException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemResultException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemResultException(string message, Exception e)
|
||||||
|
: base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !(WindowsCE)
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class WorkItemCancelException : ApplicationException
|
public sealed partial class WorkItemCancelException
|
||||||
{
|
{
|
||||||
public WorkItemCancelException() : base()
|
public WorkItemCancelException(SerializationInfo si, StreamingContext sc)
|
||||||
{
|
: base(si, sc)
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemCancelException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemCancelException(string message, Exception e) : base(message, e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemCancelException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,21 +85,10 @@ namespace Amib.Threading
|
|||||||
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class WorkItemTimeoutException : ApplicationException
|
public sealed partial class WorkItemTimeoutException
|
||||||
{
|
{
|
||||||
public WorkItemTimeoutException() : base()
|
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc)
|
||||||
{
|
: base(si, sc)
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemTimeoutException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemTimeoutException(string message, Exception e) : base(message, e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,24 +97,15 @@ namespace Amib.Threading
|
|||||||
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class WorkItemResultException : ApplicationException
|
public sealed partial class WorkItemResultException
|
||||||
{
|
{
|
||||||
public WorkItemResultException() : base()
|
public WorkItemResultException(SerializationInfo si, StreamingContext sc)
|
||||||
|
: base(si, sc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public WorkItemResultException(string message) : base(message)
|
#endif
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemResultException(string message, Exception e) : base(message, e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public WorkItemResultException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
+370
-41
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -20,16 +17,39 @@ namespace Amib.Threading
|
|||||||
/// <param name="wir">The work item result object</param>
|
/// <param name="wir">The work item result object</param>
|
||||||
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
|
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate to call after the WorkItemCallback completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wir">The work item result object</param>
|
||||||
|
public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A delegate to call when a WorkItemsGroup becomes idle
|
/// A delegate to call when a WorkItemsGroup becomes idle
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
|
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
|
||||||
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
|
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate to call after a thread is created, but before
|
||||||
|
/// it's first use.
|
||||||
|
/// </summary>
|
||||||
|
public delegate void ThreadInitializationHandler();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate to call when a thread is about to exit, after
|
||||||
|
/// it is no longer belong to the pool.
|
||||||
|
/// </summary>
|
||||||
|
public delegate void ThreadTerminationHandler();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region WorkItem Priority
|
#region WorkItem Priority
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the availeable priorities of a work item.
|
||||||
|
/// The higher the priority a work item has, the sooner
|
||||||
|
/// it will be executed.
|
||||||
|
/// </summary>
|
||||||
public enum WorkItemPriority
|
public enum WorkItemPriority
|
||||||
{
|
{
|
||||||
Lowest,
|
Lowest,
|
||||||
@@ -41,19 +61,11 @@ namespace Amib.Threading
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IHasWorkItemPriority interface
|
|
||||||
|
|
||||||
public interface IHasWorkItemPriority
|
|
||||||
{
|
|
||||||
WorkItemPriority WorkItemPriority { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IWorkItemsGroup interface
|
#region IWorkItemsGroup interface
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IWorkItemsGroup interface
|
/// IWorkItemsGroup interface
|
||||||
|
/// Created by SmartThreadPool.CreateWorkItemsGroup()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWorkItemsGroup
|
public interface IWorkItemsGroup
|
||||||
{
|
{
|
||||||
@@ -62,27 +74,263 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
string Name { get; set; }
|
string Name { get; set; }
|
||||||
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
/// <summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
/// Get/Set the maximum number of workitem that execute cocurrency on the thread pool
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
/// </summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
int Concurrency { get; set; }
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
|
||||||
|
|
||||||
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
/// <summary>
|
||||||
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
/// Get the number of work items waiting in the queue.
|
||||||
|
/// </summary>
|
||||||
|
int WaitingCallbacks { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an array with all the state objects of the currently running items.
|
||||||
|
/// The array represents a snap shot and impact performance.
|
||||||
|
/// </summary>
|
||||||
|
object[] GetStates();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the WorkItemsGroup start information
|
||||||
|
/// </summary>
|
||||||
|
WIGStartInfo WIGStartInfo { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts to execute work items
|
||||||
|
/// </summary>
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel all the work items.
|
||||||
|
/// Same as Cancel(false)
|
||||||
|
/// </summary>
|
||||||
|
void Cancel();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel all work items using thread abortion
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="abortExecution">True to stop work items by raising ThreadAbortException</param>
|
||||||
|
void Cancel(bool abortExecution);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for all work item to complete.
|
||||||
|
/// </summary>
|
||||||
void WaitForIdle();
|
void WaitForIdle();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for all work item to complete, until timeout expired
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeout">How long to wait for the work items to complete</param>
|
||||||
|
/// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
|
||||||
bool WaitForIdle(TimeSpan timeout);
|
bool WaitForIdle(TimeSpan timeout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for all work item to complete, until timeout expired
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">How long to wait for the work items to complete in milliseconds</param>
|
||||||
|
/// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
|
||||||
bool WaitForIdle(int millisecondsTimeout);
|
bool WaitForIdle(int millisecondsTimeout);
|
||||||
|
|
||||||
int WaitingCallbacks { get; }
|
/// <summary>
|
||||||
|
/// IsIdle is true when there are no work items running or queued.
|
||||||
|
/// </summary>
|
||||||
|
bool IsIdle { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This event is fired when all work items are completed.
|
||||||
|
/// (When IsIdle changes to true)
|
||||||
|
/// This event only work on WorkItemsGroup. On SmartThreadPool
|
||||||
|
/// it throws the NotImplementedException.
|
||||||
|
/// </summary>
|
||||||
event WorkItemsGroupIdleHandler OnIdle;
|
event WorkItemsGroupIdleHandler OnIdle;
|
||||||
|
|
||||||
void Cancel();
|
#region QueueWorkItem
|
||||||
void Start();
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem(Action<...>)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
|
||||||
|
IWorkItemResult QueueWorkItem(Action action);
|
||||||
|
|
||||||
|
/// <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, 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, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
|
||||||
|
|
||||||
|
#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
|
#endregion
|
||||||
@@ -92,9 +340,24 @@ namespace Amib.Threading
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum CallToPostExecute
|
public enum CallToPostExecute
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Never call to the PostExecute call back
|
||||||
|
/// </summary>
|
||||||
Never = 0x00,
|
Never = 0x00,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call to the PostExecute only when the work item is cancelled
|
||||||
|
/// </summary>
|
||||||
WhenWorkItemCanceled = 0x01,
|
WhenWorkItemCanceled = 0x01,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call to the PostExecute only when the work item is not cancelled
|
||||||
|
/// </summary>
|
||||||
WhenWorkItemNotCanceled = 0x02,
|
WhenWorkItemNotCanceled = 0x02,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Always call to the PostExecute
|
||||||
|
/// </summary>
|
||||||
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
|
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,16 +366,43 @@ namespace Amib.Threading
|
|||||||
#region IWorkItemResult interface
|
#region IWorkItemResult interface
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IWorkItemResult interface
|
/// The common interface of IWorkItemResult and IWorkItemResult<T>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWorkItemResult
|
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<T> work item is queued.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkItemResult<TResult> : IWaitableResult
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// Get the result of the work item.
|
||||||
/// If the work item didn't run yet then the caller waits.
|
/// If the work item didn't run yet then the caller waits.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
object GetResult();
|
TResult GetResult();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// Get the result of the work item.
|
||||||
@@ -120,7 +410,7 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext);
|
bool exitContext);
|
||||||
|
|
||||||
@@ -130,7 +420,7 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
bool exitContext);
|
bool exitContext);
|
||||||
|
|
||||||
@@ -146,7 +436,7 @@ namespace Amib.Threading
|
|||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
/// On cancel throws WorkItemCancelException
|
/// On cancel throws WorkItemCancelException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle);
|
WaitHandle cancelWaitHandle);
|
||||||
@@ -158,7 +448,7 @@ namespace Amib.Threading
|
|||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
/// On cancel throws WorkItemCancelException
|
/// On cancel throws WorkItemCancelException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle);
|
WaitHandle cancelWaitHandle);
|
||||||
@@ -169,16 +459,18 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
object GetResult(out Exception e);
|
TResult GetResult(out Exception e);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the result of the work item.
|
/// Get the result of the work item.
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout"></param>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</param>
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
out Exception e);
|
out Exception e);
|
||||||
@@ -187,10 +479,12 @@ namespace Amib.Threading
|
|||||||
/// Get the result of the work item.
|
/// Get the result of the work item.
|
||||||
/// If the work item didn't run yet then the caller waits until timeout.
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
/// <param name="e">Filled with the exception if one was thrown</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>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
out Exception e);
|
out Exception e);
|
||||||
@@ -208,7 +502,7 @@ namespace Amib.Threading
|
|||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
/// On cancel throws WorkItemCancelException
|
/// On cancel throws WorkItemCancelException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle,
|
WaitHandle cancelWaitHandle,
|
||||||
@@ -219,10 +513,13 @@ namespace Amib.Threading
|
|||||||
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <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="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <param name="timeout"></param>
|
||||||
|
/// <param name="exitContext"></param>
|
||||||
/// On timeout throws WorkItemTimeoutException
|
/// On timeout throws WorkItemTimeoutException
|
||||||
/// On cancel throws WorkItemCancelException
|
/// On cancel throws WorkItemCancelException
|
||||||
object GetResult(
|
TResult GetResult(
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle,
|
WaitHandle cancelWaitHandle,
|
||||||
@@ -239,16 +536,30 @@ namespace Amib.Threading
|
|||||||
bool IsCanceled { get; }
|
bool IsCanceled { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
|
/// Gets the user-defined object that contains context data
|
||||||
|
/// for the work item method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
object State { get; }
|
object State { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cancel the work item if it didn't start running yet.
|
/// Same as Cancel(false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
|
|
||||||
bool Cancel();
|
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>
|
/// <summary>
|
||||||
/// Get the work item's priority
|
/// Get the work item's priority
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -257,7 +568,7 @@ namespace Amib.Threading
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return the result, same as GetResult()
|
/// Return the result, same as GetResult()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
object Result { get; }
|
TResult Result { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the exception if occured otherwise returns null.
|
/// Returns the exception if occured otherwise returns null.
|
||||||
@@ -265,5 +576,23 @@ namespace Amib.Threading
|
|||||||
object Exception { get; }
|
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
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -25,17 +22,17 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work items queues. There is one for each type of priority
|
/// Work items queues. There is one for each type of priority
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Queue [] _queues = new Queue[_queuesCount];
|
private readonly Queue [] _queues = new Queue[_queuesCount];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The total number of work items within the queues
|
/// The total number of work items within the queues
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _workItemsCount = 0;
|
private int _workItemsCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use with IEnumerable interface
|
/// Use with IEnumerable interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _version = 0;
|
private int _version;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -159,7 +156,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private class PriorityQueueEnumerator : IEnumerator
|
private class PriorityQueueEnumerator : IEnumerator
|
||||||
{
|
{
|
||||||
private PriorityQueue _priorityQueue;
|
private readonly PriorityQueue _priorityQueue;
|
||||||
private int _version;
|
private int _version;
|
||||||
private int _queueIndex;
|
private int _queueIndex;
|
||||||
private IEnumerator _enumerator;
|
private IEnumerator _enumerator;
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("Amib.Threading")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("Amib.Threading")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("c764a3de-c4f8-434d-85b5-a09830d1e44f")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
[assembly: AssemblyVersion("2.0.0.0")]
|
||||||
|
|
||||||
@@ -3,6 +3,16 @@ using System.Diagnostics;
|
|||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
|
internal interface ISTPInstancePerformanceCounters : IDisposable
|
||||||
|
{
|
||||||
|
void Close();
|
||||||
|
void SampleThreads(long activeThreads, long inUseThreads);
|
||||||
|
void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
|
||||||
|
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
||||||
|
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
||||||
|
}
|
||||||
|
#if !(WindowsCE)
|
||||||
|
|
||||||
internal enum STPPerformanceCounterType
|
internal enum STPPerformanceCounterType
|
||||||
{
|
{
|
||||||
// Fields
|
// Fields
|
||||||
@@ -37,7 +47,7 @@ namespace Amib.Threading.Internal
|
|||||||
internal class STPPerformanceCounter
|
internal class STPPerformanceCounter
|
||||||
{
|
{
|
||||||
// Fields
|
// Fields
|
||||||
private PerformanceCounterType _pcType;
|
private readonly PerformanceCounterType _pcType;
|
||||||
protected string _counterHelp;
|
protected string _counterHelp;
|
||||||
protected string _counterName;
|
protected string _counterName;
|
||||||
|
|
||||||
@@ -47,9 +57,9 @@ namespace Amib.Threading.Internal
|
|||||||
string counterHelp,
|
string counterHelp,
|
||||||
PerformanceCounterType pcType)
|
PerformanceCounterType pcType)
|
||||||
{
|
{
|
||||||
this._counterName = counterName;
|
_counterName = counterName;
|
||||||
this._counterHelp = counterHelp;
|
_counterHelp = counterHelp;
|
||||||
this._pcType = pcType;
|
_pcType = pcType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddCounterToCollection(CounterCreationDataCollection counterData)
|
public void AddCounterToCollection(CounterCreationDataCollection counterData)
|
||||||
@@ -76,7 +86,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
// Fields
|
// Fields
|
||||||
internal STPPerformanceCounter[] _stpPerformanceCounters;
|
internal STPPerformanceCounter[] _stpPerformanceCounters;
|
||||||
private static STPPerformanceCounters _instance;
|
private static readonly STPPerformanceCounters _instance;
|
||||||
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
|
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
|
||||||
internal const string _stpCategoryName = "SmartThreadPool";
|
internal const string _stpCategoryName = "SmartThreadPool";
|
||||||
|
|
||||||
@@ -149,16 +159,18 @@ namespace Amib.Threading.Internal
|
|||||||
internal class STPInstancePerformanceCounter : IDisposable
|
internal class STPInstancePerformanceCounter : IDisposable
|
||||||
{
|
{
|
||||||
// Fields
|
// Fields
|
||||||
|
private bool _isDisposed;
|
||||||
private PerformanceCounter _pcs;
|
private PerformanceCounter _pcs;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
protected STPInstancePerformanceCounter()
|
protected STPInstancePerformanceCounter()
|
||||||
{
|
{
|
||||||
|
_isDisposed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public STPInstancePerformanceCounter(
|
public STPInstancePerformanceCounter(
|
||||||
string instance,
|
string instance,
|
||||||
STPPerformanceCounterType spcType)
|
STPPerformanceCounterType spcType) : this()
|
||||||
{
|
{
|
||||||
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
||||||
_pcs = new PerformanceCounter(
|
_pcs = new PerformanceCounter(
|
||||||
@@ -169,10 +181,6 @@ namespace Amib.Threading.Internal
|
|||||||
_pcs.RawValue = _pcs.RawValue;
|
_pcs.RawValue = _pcs.RawValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
~STPInstancePerformanceCounter()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
@@ -185,9 +193,20 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
GC.SuppressFinalize(this);
|
}
|
||||||
|
}
|
||||||
|
_isDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Increment()
|
public virtual void Increment()
|
||||||
@@ -209,27 +228,19 @@ namespace Amib.Threading.Internal
|
|||||||
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
|
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
|
||||||
{
|
{
|
||||||
// Methods
|
// Methods
|
||||||
public STPInstanceNullPerformanceCounter() {}
|
|
||||||
public override void Increment() {}
|
public override void Increment() {}
|
||||||
public override void IncrementBy(long value) {}
|
public override void IncrementBy(long value) {}
|
||||||
public override void Set(long val) {}
|
public override void Set(long val) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface ISTPInstancePerformanceCounters : IDisposable
|
|
||||||
{
|
|
||||||
void Close();
|
|
||||||
void SampleThreads(long activeThreads, long inUseThreads);
|
|
||||||
void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
|
|
||||||
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
|
||||||
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters
|
||||||
{
|
{
|
||||||
|
private bool _isDisposed;
|
||||||
// Fields
|
// Fields
|
||||||
private STPInstancePerformanceCounter[] _pcs;
|
private STPInstancePerformanceCounter[] _pcs;
|
||||||
private static STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
|
private static readonly STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
static STPInstancePerformanceCounters()
|
static STPInstancePerformanceCounters()
|
||||||
@@ -239,8 +250,13 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
public STPInstancePerformanceCounters(string instance)
|
public STPInstancePerformanceCounters(string instance)
|
||||||
{
|
{
|
||||||
|
_isDisposed = false;
|
||||||
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
|
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
|
||||||
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
|
||||||
|
// Call the STPPerformanceCounters.Instance so the static constructor will
|
||||||
|
// intialize the STPPerformanceCounters singleton.
|
||||||
|
STPPerformanceCounters.Instance.GetHashCode();
|
||||||
|
|
||||||
for (int i = 0; i < _pcs.Length; i++)
|
for (int i = 0; i < _pcs.Length; i++)
|
||||||
{
|
{
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
@@ -265,22 +281,28 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
if (null != _pcs[i])
|
if (null != _pcs[i])
|
||||||
{
|
{
|
||||||
_pcs[i].Close();
|
_pcs[i].Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_pcs = null;
|
_pcs = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~STPInstancePerformanceCounters()
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void Dispose()
|
_isDisposed = true;
|
||||||
{
|
|
||||||
Close();
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
|
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
|
||||||
@@ -320,21 +342,17 @@ namespace Amib.Threading.Internal
|
|||||||
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
|
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters
|
||||||
{
|
{
|
||||||
static NullSTPInstancePerformanceCounters()
|
private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters();
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(null);
|
|
||||||
|
|
||||||
public static NullSTPInstancePerformanceCounters Instance
|
public static NullSTPInstancePerformanceCounters Instance
|
||||||
{
|
{
|
||||||
get { return _instance; }
|
get { return _instance; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public NullSTPInstancePerformanceCounters(string instance) {}
|
|
||||||
public void Close() {}
|
public void Close() {}
|
||||||
public void Dispose() {}
|
public void Dispose() {}
|
||||||
|
|
||||||
@@ -343,5 +361,4 @@ namespace Amib.Threading.Internal
|
|||||||
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
||||||
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+178
-42
@@ -1,6 +1,4 @@
|
|||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Amib.Threading
|
namespace Amib.Threading
|
||||||
@@ -10,44 +8,18 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class STPStartInfo : WIGStartInfo
|
public class STPStartInfo : WIGStartInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
||||||
/// Idle timeout in milliseconds.
|
private int _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
||||||
/// If a thread is idle for _idleTimeout milliseconds then
|
private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
||||||
/// it may quit.
|
private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority;
|
||||||
/// </summary>
|
private string _pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
||||||
private int _idleTimeout;
|
|
||||||
|
|
||||||
/// <summary>
|
public STPStartInfo()
|
||||||
/// The lower limit of threads in the pool.
|
|
||||||
/// </summary>
|
|
||||||
private int _minWorkerThreads;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The upper limit of threads in the pool.
|
|
||||||
/// </summary>
|
|
||||||
private int _maxWorkerThreads;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The priority of the threads in the pool
|
|
||||||
/// </summary>
|
|
||||||
private ThreadPriority _threadPriority;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If this field is not null then the performance counters are enabled
|
|
||||||
/// and use the string as the name of the instance.
|
|
||||||
/// </summary>
|
|
||||||
private string _pcInstanceName;
|
|
||||||
|
|
||||||
public STPStartInfo() : base()
|
|
||||||
{
|
{
|
||||||
_idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
|
||||||
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
|
||||||
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
|
||||||
_threadPriority = SmartThreadPool.DefaultThreadPriority;
|
|
||||||
_pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public STPStartInfo(STPStartInfo stpStartInfo) : base(stpStartInfo)
|
public STPStartInfo(STPStartInfo stpStartInfo)
|
||||||
|
: base(stpStartInfo)
|
||||||
{
|
{
|
||||||
_idleTimeout = stpStartInfo._idleTimeout;
|
_idleTimeout = stpStartInfo._idleTimeout;
|
||||||
_minWorkerThreads = stpStartInfo._minWorkerThreads;
|
_minWorkerThreads = stpStartInfo._minWorkerThreads;
|
||||||
@@ -56,34 +28,198 @@ namespace Amib.Threading
|
|||||||
_pcInstanceName = stpStartInfo._pcInstanceName;
|
_pcInstanceName = stpStartInfo._pcInstanceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int IdleTimeout
|
/// <summary>
|
||||||
|
/// Get/Set the idle timeout in milliseconds.
|
||||||
|
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int IdleTimeout
|
||||||
{
|
{
|
||||||
get { return _idleTimeout; }
|
get { return _idleTimeout; }
|
||||||
set { _idleTimeout = value; }
|
set { _idleTimeout = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MinWorkerThreads
|
/// <summary>
|
||||||
|
/// Get/Set the lower limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int MinWorkerThreads
|
||||||
{
|
{
|
||||||
get { return _minWorkerThreads; }
|
get { return _minWorkerThreads; }
|
||||||
set { _minWorkerThreads = value; }
|
set { _minWorkerThreads = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int MaxWorkerThreads
|
/// <summary>
|
||||||
|
/// Get/Set the upper limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int MaxWorkerThreads
|
||||||
{
|
{
|
||||||
get { return _maxWorkerThreads; }
|
get { return _maxWorkerThreads; }
|
||||||
set { _maxWorkerThreads = value; }
|
set { _maxWorkerThreads = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadPriority ThreadPriority
|
/// <summary>
|
||||||
|
/// Get/Set the scheduling priority of the threads in the pool.
|
||||||
|
/// The Os handles the scheduling.
|
||||||
|
/// </summary>
|
||||||
|
public virtual ThreadPriority ThreadPriority
|
||||||
{
|
{
|
||||||
get { return _threadPriority; }
|
get { return _threadPriority; }
|
||||||
set { _threadPriority = value; }
|
set { _threadPriority = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string PerformanceCounterInstanceName
|
/// <summary>
|
||||||
|
/// Get/Set the performance counter instance name of this SmartThreadPool
|
||||||
|
/// The default is null which indicate not to use performance counters at all.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string PerformanceCounterInstanceName
|
||||||
{
|
{
|
||||||
get { return _pcInstanceName; }
|
get { return _pcInstanceName; }
|
||||||
set { _pcInstanceName = value; }
|
set { _pcInstanceName = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a readonly version of this STPStartInfo.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a readonly reference to this STPStartInfo</returns>
|
||||||
|
public new STPStartInfo AsReadOnly()
|
||||||
|
{
|
||||||
|
return new STPStartInfoRO(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region STPStartInfoRO class
|
||||||
|
|
||||||
|
private class STPStartInfoRO : STPStartInfo
|
||||||
|
{
|
||||||
|
private readonly STPStartInfo _stpStartInfo;
|
||||||
|
|
||||||
|
public STPStartInfoRO(STPStartInfo stpStartInfo)
|
||||||
|
{
|
||||||
|
_stpStartInfo = stpStartInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the idle timeout in milliseconds.
|
||||||
|
/// If a thread is idle (starved) longer than IdleTimeout then it may quit.
|
||||||
|
/// </summary>
|
||||||
|
public override int IdleTimeout
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.IdleTimeout; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the lower limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
public override int MinWorkerThreads
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.MinWorkerThreads; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the upper limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
public override int MaxWorkerThreads
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.MaxWorkerThreads; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the scheduling priority of the threads in the pool.
|
||||||
|
/// The Os handles the scheduling.
|
||||||
|
/// </summary>
|
||||||
|
public override ThreadPriority ThreadPriority
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.ThreadPriority; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the performance counter instance name of this SmartThreadPool
|
||||||
|
/// The default is null which indicate not to use performance counters at all.
|
||||||
|
/// </summary>
|
||||||
|
public override string PerformanceCounterInstanceName
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.PerformanceCounterInstanceName; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
public override bool UseCallerCallContext
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.UseCallerCallContext; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
|
public override bool UseCallerHttpContext
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.UseCallerHttpContext; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
|
public override bool DisposeOfStateObjects
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.DisposeOfStateObjects; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the run the post execute options
|
||||||
|
/// </summary>
|
||||||
|
public override CallToPostExecute CallToPostExecute
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.CallToPostExecute; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default post execute callback
|
||||||
|
/// </summary>
|
||||||
|
public override PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.PostExecuteWorkItemCallback; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if the work items execution should be suspended until the Start()
|
||||||
|
/// method is called.
|
||||||
|
/// </summary>
|
||||||
|
public override bool StartSuspended
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.StartSuspended; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default priority that a work item gets when it is enqueued
|
||||||
|
/// </summary>
|
||||||
|
public override WorkItemPriority WorkItemPriority
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.WorkItemPriority; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate if QueueWorkItem of Action<...>/Func<...> fill the
|
||||||
|
/// arguments as an object array into the state of the work item.
|
||||||
|
/// The arguments can be access later by IWorkItemResult.State.
|
||||||
|
/// </summary>
|
||||||
|
public override bool FillStateWithArgs
|
||||||
|
{
|
||||||
|
get { return _stpStartInfo.FillStateWithArgs; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+553
-419
File diff suppressed because it is too large
Load Diff
@@ -1,141 +1,70 @@
|
|||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectType>Local</ProjectType>
|
|
||||||
<ProductVersion>8.0.50727</ProductVersion>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectGuid>{8684FC56-A679-4E2E-8F96-E172FB062EB6}</ProjectGuid>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ApplicationIcon>
|
<ProjectGuid>{74D4C33F-7CC8-4B2A-A7DF-D8B6E63B6EBD}</ProjectGuid>
|
||||||
</ApplicationIcon>
|
|
||||||
<AssemblyKeyContainerName>
|
|
||||||
</AssemblyKeyContainerName>
|
|
||||||
<AssemblyName>SmartThreadPool</AssemblyName>
|
|
||||||
<AssemblyOriginatorKeyFile>
|
|
||||||
</AssemblyOriginatorKeyFile>
|
|
||||||
<DefaultClientScript>JScript</DefaultClientScript>
|
|
||||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
|
||||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
|
||||||
<DelaySign>false</DelaySign>
|
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RootNamespace>SmartThreadPool</RootNamespace>
|
<NoStandardLibraries>false</NoStandardLibraries>
|
||||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
<AssemblyName>SmartThreadPool</AssemblyName>
|
||||||
<StartupObject>
|
<RootNamespace>Amib.Threading</RootNamespace>
|
||||||
</StartupObject>
|
|
||||||
<FileUpgradeFlags>
|
|
||||||
</FileUpgradeFlags>
|
|
||||||
<UpgradeBackupLocation>
|
|
||||||
</UpgradeBackupLocation>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
<DebugType>full</DebugType>
|
||||||
<BaseAddress>285212672</BaseAddress>
|
<Optimize>false</Optimize>
|
||||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
<OutputPath>.\bin\Debug\</OutputPath>
|
||||||
<ConfigurationOverrideFile>
|
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||||
</ConfigurationOverrideFile>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<DocumentationFile>
|
<DocumentationFile>
|
||||||
</DocumentationFile>
|
</DocumentationFile>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<FileAlignment>4096</FileAlignment>
|
|
||||||
<NoStdLib>false</NoStdLib>
|
|
||||||
<NoWarn>
|
|
||||||
</NoWarn>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<RegisterForComInterop>false</RegisterForComInterop>
|
|
||||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
|
||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<DebugType>pdbonly</DebugType>
|
||||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
|
||||||
<BaseAddress>285212672</BaseAddress>
|
|
||||||
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
|
||||||
<ConfigurationOverrideFile>
|
|
||||||
</ConfigurationOverrideFile>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<DocumentationFile>
|
|
||||||
</DocumentationFile>
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
|
||||||
<FileAlignment>4096</FileAlignment>
|
|
||||||
<NoStdLib>false</NoStdLib>
|
|
||||||
<NoWarn>
|
|
||||||
</NoWarn>
|
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<RegisterForComInterop>false</RegisterForComInterop>
|
<OutputPath>.\bin\Release\</OutputPath>
|
||||||
<RemoveIntegerChecks>false</RemoveIntegerChecks>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
</PropertyGroup>
|
||||||
<WarningLevel>4</WarningLevel>
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugCE|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<OutputPath>bin\DebugCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System">
|
<Reference Include="System" />
|
||||||
<Name>System</Name>
|
<Reference Include="System.Data" />
|
||||||
</Reference>
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Data">
|
<Reference Include="System.Xml" />
|
||||||
<Name>System.Data</Name>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Web">
|
|
||||||
<Name>System.Web</Name>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System.Xml">
|
|
||||||
<Name>System.XML</Name>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AssemblyInfo.cs">
|
<Compile Include="CallerThreadContext.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="EventWaitHandleFactory.cs" />
|
||||||
</Compile>
|
<Compile Include="Exceptions.cs" />
|
||||||
<Compile Include="CallerThreadContext.cs">
|
<Compile Include="Interfaces.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="PriorityQueue.cs" />
|
||||||
</Compile>
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Exceptions.cs">
|
<Compile Include="SmartThreadPool.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="STPPerformanceCounter.cs" />
|
||||||
</Compile>
|
<Compile Include="STPStartInfo.cs" />
|
||||||
<Compile Include="Interfaces.cs">
|
<Compile Include="SynchronizedDictionary.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="WIGStartInfo.cs" />
|
||||||
</Compile>
|
<Compile Include="WorkItem.cs" />
|
||||||
<Compile Include="PriorityQueue.cs">
|
<Compile Include="WorkItemFactory.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="WorkItemInfo.cs" />
|
||||||
</Compile>
|
<Compile Include="WorkItemResultTWrapper.cs" />
|
||||||
<Compile Include="SmartThreadPool.cs">
|
<Compile Include="WorkItemsGroup.cs" />
|
||||||
<SubType>Code</SubType>
|
<Compile Include="WorkItemsGroupBase.cs" />
|
||||||
</Compile>
|
<Compile Include="WorkItemsQueue.cs" />
|
||||||
<Compile Include="STPPerformanceCounter.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="STPStartInfo.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WIGStartInfo.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WorkItem.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WorkItemFactory.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WorkItemInfo.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WorkItemsGroup.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="WorkItemsQueue.cs">
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
|
||||||
<PropertyGroup>
|
<ProjectExtensions>
|
||||||
<PreBuildEvent>
|
<VisualStudio AllowExistingFolder="true" />
|
||||||
</PreBuildEvent>
|
</ProjectExtensions>
|
||||||
<PostBuildEvent>
|
|
||||||
</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.50727</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{D81DD596-C71F-4AC2-816C-63C19589E7E0}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>Amib.Threading</RootNamespace>
|
||||||
|
<AssemblyName>SmartThreadPoolCE</AssemblyName>
|
||||||
|
<ProjectTypeGuids>{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
|
||||||
|
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
|
||||||
|
<OSVersion>5.0</OSVersion>
|
||||||
|
<DeployDirSuffix>SmartThreadPoolCE</DeployDirSuffix>
|
||||||
|
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||||
|
<FormFactorID>
|
||||||
|
</FormFactorID>
|
||||||
|
<SignAssembly>false</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>
|
||||||
|
</AssemblyOriginatorKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;$(PlatformFamilyName)</DefineConstants>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE;WindowsCE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="CallerThreadContext.cs" />
|
||||||
|
<Compile Include="EventWaitHandle.cs" />
|
||||||
|
<Compile Include="EventWaitHandleFactory.cs" />
|
||||||
|
<Compile Include="Exceptions.cs" />
|
||||||
|
<Compile Include="Interfaces.cs" />
|
||||||
|
<Compile Include="PriorityQueue.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="SmartThreadPool.cs" />
|
||||||
|
<Compile Include="STPPerformanceCounter.cs" />
|
||||||
|
<Compile Include="STPStartInfo.cs" />
|
||||||
|
<Compile Include="SynchronizedDictionary.cs" />
|
||||||
|
<Compile Include="WIGStartInfo.cs" />
|
||||||
|
<Compile Include="WorkItem.cs" />
|
||||||
|
<Compile Include="WorkItemFactory.cs" />
|
||||||
|
<Compile Include="WorkItemInfo.cs" />
|
||||||
|
<Compile Include="WorkItemResultTWrapper.cs" />
|
||||||
|
<Compile Include="WorkItemsGroup.cs" />
|
||||||
|
<Compile Include="WorkItemsGroupBase.cs" />
|
||||||
|
<Compile Include="WorkItemsQueue.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Condition="'$(TargetFrameworkVersion)' == 'v1.0'" Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.v1.targets" />
|
||||||
|
<Import Condition="'$(TargetFrameworkVersion)' == 'v2.0'" Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||||
|
<ProjectExtensions>
|
||||||
|
<VisualStudio>
|
||||||
|
<FlavorProperties GUID="{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}">
|
||||||
|
<HostingProcess disable="1" />
|
||||||
|
</FlavorProperties>
|
||||||
|
</VisualStudio>
|
||||||
|
</ProjectExtensions>
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+156
-45
@@ -1,5 +1,4 @@
|
|||||||
// Ami Bar
|
using System;
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
namespace Amib.Threading
|
namespace Amib.Threading
|
||||||
{
|
{
|
||||||
@@ -8,46 +7,17 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class WIGStartInfo
|
public class WIGStartInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
private bool _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
||||||
/// Use the caller's security context
|
private bool _useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
||||||
/// </summary>
|
private bool _disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
||||||
private bool _useCallerCallContext;
|
private CallToPostExecute _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
||||||
|
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
||||||
/// <summary>
|
private WorkItemPriority _workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
|
||||||
/// Use the caller's HTTP context
|
private bool _startSuspended = SmartThreadPool.DefaultStartSuspended;
|
||||||
/// </summary>
|
private bool _fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
|
||||||
private bool _useCallerHttpContext;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispose of the state object of a work item
|
|
||||||
/// </summary>
|
|
||||||
private bool _disposeOfStateObjects;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The option to run the post execute
|
|
||||||
/// </summary>
|
|
||||||
private CallToPostExecute _callToPostExecute;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A post execute callback to call when none is provided in
|
|
||||||
/// the QueueWorkItem method.
|
|
||||||
/// </summary>
|
|
||||||
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicate the WorkItemsGroup to suspend the handling of the work items
|
|
||||||
/// until the Start() method is called.
|
|
||||||
/// </summary>
|
|
||||||
private bool _startSuspended;
|
|
||||||
|
|
||||||
public WIGStartInfo()
|
public WIGStartInfo()
|
||||||
{
|
{
|
||||||
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
|
||||||
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
|
||||||
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
|
||||||
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
|
||||||
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
|
||||||
_startSuspended = SmartThreadPool.DefaultStartSuspended;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public WIGStartInfo(WIGStartInfo wigStartInfo)
|
public WIGStartInfo(WIGStartInfo wigStartInfo)
|
||||||
@@ -57,43 +27,184 @@ namespace Amib.Threading
|
|||||||
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
|
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
|
||||||
_callToPostExecute = wigStartInfo._callToPostExecute;
|
_callToPostExecute = wigStartInfo._callToPostExecute;
|
||||||
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
|
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
|
||||||
|
_workItemPriority = wigStartInfo._workItemPriority;
|
||||||
_startSuspended = wigStartInfo._startSuspended;
|
_startSuspended = wigStartInfo._startSuspended;
|
||||||
|
_fillStateWithArgs = wigStartInfo._fillStateWithArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseCallerCallContext
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool UseCallerCallContext
|
||||||
{
|
{
|
||||||
get { return _useCallerCallContext; }
|
get { return _useCallerCallContext; }
|
||||||
set { _useCallerCallContext = value; }
|
set { _useCallerCallContext = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseCallerHttpContext
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool UseCallerHttpContext
|
||||||
{
|
{
|
||||||
get { return _useCallerHttpContext; }
|
get { return _useCallerHttpContext; }
|
||||||
set { _useCallerHttpContext = value; }
|
set { _useCallerHttpContext = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisposeOfStateObjects
|
/// <summary>
|
||||||
|
/// Get/Set if to dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool DisposeOfStateObjects
|
||||||
{
|
{
|
||||||
get { return _disposeOfStateObjects; }
|
get { return _disposeOfStateObjects; }
|
||||||
set { _disposeOfStateObjects = value; }
|
set { _disposeOfStateObjects = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallToPostExecute CallToPostExecute
|
/// <summary>
|
||||||
|
/// Get/Set the run the post execute options
|
||||||
|
/// </summary>
|
||||||
|
public virtual CallToPostExecute CallToPostExecute
|
||||||
{
|
{
|
||||||
get { return _callToPostExecute; }
|
get { return _callToPostExecute; }
|
||||||
set { _callToPostExecute = value; }
|
set { _callToPostExecute = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
/// <summary>
|
||||||
|
/// Get/Set the default post execute callback
|
||||||
|
/// </summary>
|
||||||
|
public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
{
|
{
|
||||||
get { return _postExecuteWorkItemCallback; }
|
get { return _postExecuteWorkItemCallback; }
|
||||||
set { _postExecuteWorkItemCallback = value; }
|
set { _postExecuteWorkItemCallback = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StartSuspended
|
/// <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; }
|
get { return _startSuspended; }
|
||||||
set { _startSuspended = value; }
|
set { _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 { _fillStateWithArgs = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a readonly version of this WIGStartInfo
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns a readonly reference to this WIGStartInfoRO</returns>
|
||||||
|
public WIGStartInfo AsReadOnly()
|
||||||
|
{
|
||||||
|
return new WIGStartInfoRO(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region WIGStartInfoRO class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A readonly version of WIGStartInfo
|
||||||
|
/// </summary>
|
||||||
|
private class WIGStartInfoRO : WIGStartInfo
|
||||||
|
{
|
||||||
|
private readonly WIGStartInfo _wigStartInfoRO;
|
||||||
|
|
||||||
|
public WIGStartInfoRO(WIGStartInfo wigStartInfoRO)
|
||||||
|
{
|
||||||
|
_wigStartInfoRO = wigStartInfoRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
public override bool UseCallerCallContext
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.UseCallerCallContext; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
|
public override bool UseCallerHttpContext
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.UseCallerHttpContext; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if to dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
|
public override bool DisposeOfStateObjects
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.DisposeOfStateObjects; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the run the post execute options
|
||||||
|
/// </summary>
|
||||||
|
public override CallToPostExecute CallToPostExecute
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.CallToPostExecute; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default post execute callback
|
||||||
|
/// </summary>
|
||||||
|
public override PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.PostExecuteWorkItemCallback; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if the work items execution should be suspended until the Start()
|
||||||
|
/// method is called.
|
||||||
|
/// </summary>
|
||||||
|
public override bool StartSuspended
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.StartSuspended; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default priority that a work item gets when it is enqueued
|
||||||
|
/// </summary>
|
||||||
|
public override WorkItemPriority WorkItemPriority
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.WorkItemPriority; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate if QueueWorkItem of Action<...>/Func<...> fill the
|
||||||
|
/// arguments as an object array into the state of the work item.
|
||||||
|
/// The arguments can be access later by IWorkItemResult.State.
|
||||||
|
/// </summary>
|
||||||
|
public override bool FillStateWithArgs
|
||||||
|
{
|
||||||
|
get { return _wigStartInfoRO.FillStateWithArgs; }
|
||||||
|
set { throw new NotSupportedException("This is a readonly instance and set is not supported"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+250
-78
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -16,7 +13,7 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IInternalWorkItemResult interface
|
#region CanceledWorkItemsGroup class
|
||||||
|
|
||||||
public class CanceledWorkItemsGroup
|
public class CanceledWorkItemsGroup
|
||||||
{
|
{
|
||||||
@@ -30,6 +27,10 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IInternalWorkItemResult interface
|
||||||
|
|
||||||
internal interface IInternalWorkItemResult
|
internal interface IInternalWorkItemResult
|
||||||
{
|
{
|
||||||
event WorkItemStateCallback OnWorkItemStarted;
|
event WorkItemStateCallback OnWorkItemStarted;
|
||||||
@@ -38,11 +39,23 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IWorkItem interface
|
#region IInternalWaitableResult interface
|
||||||
|
|
||||||
public interface IWorkItem
|
internal interface IInternalWaitableResult
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This method is intent for internal use.
|
||||||
|
/// </summary>
|
||||||
|
IWorkItemResult GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IHasWorkItemPriority interface
|
||||||
|
|
||||||
|
public interface IHasWorkItemPriority
|
||||||
|
{
|
||||||
|
WorkItemPriority WorkItemPriority { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -52,7 +65,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds a callback delegate and the state for that delegate.
|
/// Holds a callback delegate and the state for that delegate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WorkItem : IHasWorkItemPriority, IWorkItem
|
public class WorkItem : IHasWorkItemPriority
|
||||||
{
|
{
|
||||||
#region WorkItemState enum
|
#region WorkItemState enum
|
||||||
|
|
||||||
@@ -61,20 +74,45 @@ namespace Amib.Threading.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private enum WorkItemState
|
private enum WorkItemState
|
||||||
{
|
{
|
||||||
InQueue,
|
InQueue = 0, // Nexts: InProgress, Canceled
|
||||||
InProgress,
|
InProgress = 1, // Nexts: Completed, Canceled
|
||||||
Completed,
|
Completed = 2, // Stays Completed
|
||||||
Canceled,
|
Canceled = 3, // Stays Canceled
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidStatesTransition(WorkItemState currentState, WorkItemState nextState)
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
switch (currentState)
|
||||||
|
{
|
||||||
|
case WorkItemState.InQueue:
|
||||||
|
valid = (WorkItemState.InProgress == nextState) || (WorkItemState.Canceled == nextState);
|
||||||
|
break;
|
||||||
|
case WorkItemState.InProgress:
|
||||||
|
valid = (WorkItemState.Completed == nextState) || (WorkItemState.Canceled == nextState);
|
||||||
|
break;
|
||||||
|
case WorkItemState.Completed:
|
||||||
|
case WorkItemState.Canceled:
|
||||||
|
// Cannot be changed
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown state
|
||||||
|
Debug.Assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Member Variables
|
#region Fields
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Callback delegate for the callback.
|
/// Callback delegate for the callback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItemCallback _callback;
|
private readonly WorkItemCallback _callback;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// State with which to call the callback delegate.
|
/// State with which to call the callback delegate.
|
||||||
@@ -84,8 +122,9 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stores the caller's context
|
/// Stores the caller's context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private CallerThreadContext _callerContext;
|
#if !(WindowsCE)
|
||||||
|
private readonly CallerThreadContext _callerContext;
|
||||||
|
#endif
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds the result of the mehtod
|
/// Holds the result of the mehtod
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -115,12 +154,12 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the result state of the work item
|
/// Represents the result state of the work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItemResult _workItemResult;
|
private readonly WorkItemResult _workItemResult;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work item info
|
/// Work item info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItemInfo _workItemInfo;
|
private readonly WorkItemInfo _workItemInfo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the WorkItem starts
|
/// Called when the WorkItem starts
|
||||||
@@ -139,10 +178,21 @@ namespace Amib.Threading.Internal
|
|||||||
private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The work item group this work item belong to.
|
/// A reference to an object that indicates whatever the
|
||||||
///
|
/// SmartThreadPool has been canceled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IWorkItemsGroup _workItemsGroup;
|
private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The work item group this work item belong to.
|
||||||
|
/// </summary>
|
||||||
|
private readonly IWorkItemsGroup _workItemsGroup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The thread that executes this workitem.
|
||||||
|
/// This field is available for the period when the work item is executed, before and after it is null.
|
||||||
|
/// </summary>
|
||||||
|
private Thread _executingThread;
|
||||||
|
|
||||||
#region Performance Counter fields
|
#region Performance Counter fields
|
||||||
|
|
||||||
@@ -193,6 +243,8 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize the callback holding object.
|
/// Initialize the callback holding object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The workItemGroup of the workitem</param>
|
||||||
|
/// <param name="workItemInfo">The WorkItemInfo of te workitem</param>
|
||||||
/// <param name="callback">Callback delegate for the callback.</param>
|
/// <param name="callback">Callback delegate for the callback.</param>
|
||||||
/// <param name="state">State with which to call the callback delegate.</param>
|
/// <param name="state">State with which to call the callback delegate.</param>
|
||||||
///
|
///
|
||||||
@@ -207,10 +259,12 @@ namespace Amib.Threading.Internal
|
|||||||
_workItemsGroup = workItemsGroup;
|
_workItemsGroup = workItemsGroup;
|
||||||
_workItemInfo = workItemInfo;
|
_workItemInfo = workItemInfo;
|
||||||
|
|
||||||
|
#if !(WindowsCE)
|
||||||
if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
|
if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
|
||||||
{
|
{
|
||||||
_callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
|
_callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
_state = state;
|
_state = state;
|
||||||
@@ -220,7 +274,10 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
{
|
{
|
||||||
|
// The _workItemState is changed directly instead of using the SetWorkItemState
|
||||||
|
// method since we don't want to go throught IsValidStateTransition.
|
||||||
_workItemState = WorkItemState.InQueue;
|
_workItemState = WorkItemState.InQueue;
|
||||||
|
|
||||||
_workItemCompleted = null;
|
_workItemCompleted = null;
|
||||||
_workItemCompletedRefCount = 0;
|
_workItemCompletedRefCount = 0;
|
||||||
}
|
}
|
||||||
@@ -237,15 +294,14 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
public CanceledWorkItemsGroup CanceledWorkItemsGroup
|
public CanceledWorkItemsGroup CanceledWorkItemsGroup
|
||||||
{
|
{
|
||||||
get
|
get { return _canceledWorkItemsGroup; }
|
||||||
{
|
set { _canceledWorkItemsGroup = value; }
|
||||||
return _canceledWorkItemsGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
public CanceledWorkItemsGroup CanceledSmartThreadPool
|
||||||
{
|
{
|
||||||
_canceledWorkItemsGroup = value;
|
get { return _canceledSmartThreadPool; }
|
||||||
}
|
set { _canceledSmartThreadPool = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -275,6 +331,9 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
|
Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
|
||||||
|
|
||||||
|
// No need for a lock yet, only after the state has changed to InProgress
|
||||||
|
_executingThread = Thread.CurrentThread;
|
||||||
|
|
||||||
SetWorkItemState(WorkItemState.InProgress);
|
SetWorkItemState(WorkItemState.InProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,25 +380,43 @@ namespace Amib.Threading.Internal
|
|||||||
_workItemCompletedEvent(this);
|
_workItemCompletedEvent(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch // Ignore exceptions
|
catch // Suppress exceptions
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void FireWorkItemStarted()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (null != _workItemStartedEvent)
|
||||||
|
{
|
||||||
|
_workItemStartedEvent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch // Suppress exceptions
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Execute the work item
|
/// Execute the work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ExecuteWorkItem()
|
private void ExecuteWorkItem()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
#if !(WindowsCE)
|
||||||
CallerThreadContext ctc = null;
|
CallerThreadContext ctc = null;
|
||||||
if (null != _callerContext)
|
if (null != _callerContext)
|
||||||
{
|
{
|
||||||
ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext);
|
ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext);
|
||||||
CallerThreadContext.Apply(_callerContext);
|
CallerThreadContext.Apply(_callerContext);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
object result = null;
|
object result = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = _callback(_state);
|
result = _callback(_state);
|
||||||
@@ -350,12 +427,42 @@ namespace Amib.Threading.Internal
|
|||||||
exception = e;
|
exception = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the value of the execution thread, so it will not be possible to cancel the work item
|
||||||
|
// since it is already completed.
|
||||||
|
// Cancelling a work item that already completed may cause the abortion of the next work item!!!
|
||||||
|
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
||||||
|
|
||||||
|
if (null == executionThread)
|
||||||
|
{
|
||||||
|
// Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException
|
||||||
|
Thread.Sleep(60*1000);
|
||||||
|
|
||||||
|
// If after 1 minute this thread was not aborted then let it continue working.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We must treat the ThreadAbortException or else it will be stored in the exception variable
|
||||||
|
catch (ThreadAbortException tae)
|
||||||
|
{
|
||||||
|
// Check if the work item was cancelled
|
||||||
|
if ((string)tae.ExceptionState == "Cancel")
|
||||||
|
{
|
||||||
|
#if !(WindowsCE)
|
||||||
|
Thread.ResetAbort();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(WindowsCE)
|
||||||
if (null != _callerContext)
|
if (null != _callerContext)
|
||||||
{
|
{
|
||||||
CallerThreadContext.Apply(ctc);
|
CallerThreadContext.Apply(ctc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!SmartThreadPool.IsWorkItemCanceled)
|
||||||
|
{
|
||||||
SetResult(result, exception);
|
SetResult(result, exception);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -367,7 +474,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_workItemInfo.PostExecuteWorkItemCallback(this._workItemResult);
|
_workItemInfo.PostExecuteWorkItemCallback(_workItemResult);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -380,6 +487,8 @@ namespace Amib.Threading.Internal
|
|||||||
/// Set the result of the work item to return
|
/// Set the result of the work item to return
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result">The result of the work item</param>
|
/// <param name="result">The result of the work item</param>
|
||||||
|
/// <param name="exception">The exception that was throw while the workitem executed, null
|
||||||
|
/// if there was no exception.</param>
|
||||||
internal void SetResult(object result, Exception exception)
|
internal void SetResult(object result, Exception exception)
|
||||||
{
|
{
|
||||||
_result = result;
|
_result = result;
|
||||||
@@ -399,33 +508,33 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wait for all work items to complete
|
/// Wait for all work items to complete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="workItemResults">Array of work item result objects</param>
|
/// <param name="waitableResults">Array of work item result objects</param>
|
||||||
/// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
|
/// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
|
||||||
/// <param name="exitContext">
|
/// <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.
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
|
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// true when every work item in workItemResults has completed; otherwise false.
|
/// true when every work item in waitableResults has completed; otherwise false.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
internal static bool WaitAll(
|
internal static bool WaitAll(
|
||||||
IWorkItemResult [] workItemResults,
|
IWaitableResult[] waitableResults,
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle)
|
WaitHandle cancelWaitHandle)
|
||||||
{
|
{
|
||||||
if (0 == workItemResults.Length)
|
if (0 == waitableResults.Length)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
WaitHandle [] waitHandles = new WaitHandle[workItemResults.Length];;
|
WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
|
||||||
GetWaitHandles(workItemResults, waitHandles);
|
GetWaitHandles(waitableResults, waitHandles);
|
||||||
|
|
||||||
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
|
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
|
||||||
{
|
{
|
||||||
success = WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
success = EventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -448,7 +557,7 @@ namespace Amib.Threading.Internal
|
|||||||
// We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
|
// We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
|
||||||
// won't affect it.
|
// won't affect it.
|
||||||
// Each iteration we update the time left for the timeout.
|
// Each iteration we update the time left for the timeout.
|
||||||
for(int i = 0; i < workItemResults.Length; ++i)
|
for (int i = 0; i < waitableResults.Length; ++i)
|
||||||
{
|
{
|
||||||
// WaitAny don't work with negative numbers
|
// WaitAny don't work with negative numbers
|
||||||
if (!waitInfinitely && (millisecondsLeft < 0))
|
if (!waitInfinitely && (millisecondsLeft < 0))
|
||||||
@@ -458,8 +567,8 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
whs[0] = waitHandles[i];
|
whs[0] = waitHandles[i];
|
||||||
int result = WaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
|
int result = EventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
|
||||||
if((result > 0) || (WaitHandle.WaitTimeout == result))
|
if ((result > 0) || (EventWaitHandle.WaitTimeout == result))
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
@@ -474,7 +583,7 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Release the wait handles
|
// Release the wait handles
|
||||||
ReleaseWaitHandles(workItemResults);
|
ReleaseWaitHandles(waitableResults);
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -482,7 +591,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits for any of the work items in the specified array to complete, cancel, or timeout
|
/// Waits for any of the work items in the specified array to complete, cancel, or timeout
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="workItemResults">Array of work item result objects</param>
|
/// <param name="waitableResults">Array of work item result objects</param>
|
||||||
/// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
|
/// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
|
||||||
/// <param name="exitContext">
|
/// <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.
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
@@ -492,37 +601,37 @@ namespace Amib.Threading.Internal
|
|||||||
/// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
|
/// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
internal static int WaitAny(
|
internal static int WaitAny(
|
||||||
IWorkItemResult [] workItemResults,
|
IWaitableResult[] waitableResults,
|
||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle)
|
WaitHandle cancelWaitHandle)
|
||||||
{
|
{
|
||||||
WaitHandle [] waitHandles = null;
|
WaitHandle [] waitHandles;
|
||||||
|
|
||||||
if (null != cancelWaitHandle)
|
if (null != cancelWaitHandle)
|
||||||
{
|
{
|
||||||
waitHandles = new WaitHandle[workItemResults.Length+1];
|
waitHandles = new WaitHandle[waitableResults.Length + 1];
|
||||||
GetWaitHandles(workItemResults, waitHandles);
|
GetWaitHandles(waitableResults, waitHandles);
|
||||||
waitHandles[workItemResults.Length] = cancelWaitHandle;
|
waitHandles[waitableResults.Length] = cancelWaitHandle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
waitHandles = new WaitHandle[workItemResults.Length];
|
waitHandles = new WaitHandle[waitableResults.Length];
|
||||||
GetWaitHandles(workItemResults, waitHandles);
|
GetWaitHandles(waitableResults, waitHandles);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
int result = EventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||||
|
|
||||||
// Treat cancel as timeout
|
// Treat cancel as timeout
|
||||||
if (null != cancelWaitHandle)
|
if (null != cancelWaitHandle)
|
||||||
{
|
{
|
||||||
if (result == workItemResults.Length)
|
if (result == waitableResults.Length)
|
||||||
{
|
{
|
||||||
result = WaitHandle.WaitTimeout;
|
result = EventWaitHandle.WaitTimeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseWaitHandles(workItemResults);
|
ReleaseWaitHandles(waitableResults);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -530,16 +639,16 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fill an array of wait handles with the work items wait handles.
|
/// Fill an array of wait handles with the work items wait handles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="workItemResults">An array of work item results</param>
|
/// <param name="waitableResults">An array of work item results</param>
|
||||||
/// <param name="waitHandles">An array of wait handles to fill</param>
|
/// <param name="waitHandles">An array of wait handles to fill</param>
|
||||||
private static void GetWaitHandles(
|
private static void GetWaitHandles(
|
||||||
IWorkItemResult [] workItemResults,
|
IWaitableResult[] waitableResults,
|
||||||
WaitHandle [] waitHandles)
|
WaitHandle [] waitHandles)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < workItemResults.Length; ++i)
|
for (int i = 0; i < waitableResults.Length; ++i)
|
||||||
{
|
{
|
||||||
WorkItemResult wir = workItemResults[i] as WorkItemResult;
|
WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
|
||||||
Debug.Assert(null != wir, "All workItemResults must be WorkItemResult objects");
|
Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects");
|
||||||
|
|
||||||
waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
|
waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
|
||||||
}
|
}
|
||||||
@@ -548,31 +657,40 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Release the work items' wait handles
|
/// Release the work items' wait handles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="workItemResults">An array of work item results</param>
|
/// <param name="waitableResults">An array of work item results</param>
|
||||||
private static void ReleaseWaitHandles(IWorkItemResult [] workItemResults)
|
private static void ReleaseWaitHandles(IWaitableResult[] waitableResults)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < workItemResults.Length; ++i)
|
for (int i = 0; i < waitableResults.Length; ++i)
|
||||||
{
|
{
|
||||||
WorkItemResult wir = workItemResults[i] as WorkItemResult;
|
WorkItemResult wir = (WorkItemResult)waitableResults[i].GetWorkItemResult();
|
||||||
|
|
||||||
wir.GetWorkItem().ReleaseWaitHandle();
|
wir.GetWorkItem().ReleaseWaitHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private Members
|
#region Private Members
|
||||||
|
|
||||||
private WorkItemState GetWorkItemState()
|
private WorkItemState GetWorkItemState()
|
||||||
{
|
{
|
||||||
if (_canceledWorkItemsGroup.IsCanceled)
|
lock (this)
|
||||||
|
{
|
||||||
|
if (WorkItemState.Completed == _workItemState || WorkItemState.InProgress == _workItemState)
|
||||||
|
{
|
||||||
|
return _workItemState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanceledSmartThreadPool.IsCanceled || CanceledWorkItemsGroup.IsCanceled)
|
||||||
{
|
{
|
||||||
return WorkItemState.Canceled;
|
return WorkItemState.Canceled;
|
||||||
}
|
}
|
||||||
return _workItemState;
|
|
||||||
|
|
||||||
|
return _workItemState;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the work item's state
|
/// Sets the work item's state
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -580,10 +698,13 @@ namespace Amib.Threading.Internal
|
|||||||
private void SetWorkItemState(WorkItemState workItemState)
|
private void SetWorkItemState(WorkItemState workItemState)
|
||||||
{
|
{
|
||||||
lock(this)
|
lock(this)
|
||||||
|
{
|
||||||
|
if (IsValidStatesTransition(_workItemState, workItemState))
|
||||||
{
|
{
|
||||||
_workItemState = workItemState;
|
_workItemState = workItemState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signals that work item has been completed or canceled
|
/// Signals that work item has been completed or canceled
|
||||||
@@ -615,29 +736,61 @@ namespace Amib.Threading.Internal
|
|||||||
/// Cancel the work item if it didn't start running yet.
|
/// Cancel the work item if it didn't start running yet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
|
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
|
||||||
private bool Cancel()
|
private bool Cancel(bool abortExecution)
|
||||||
{
|
{
|
||||||
lock(this)
|
#if (WindowsCE)
|
||||||
|
if(abortExecution)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("abortExecution", "WindowsCE doesn't support this feature");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
bool success = false;
|
||||||
|
bool signalComplete = false;
|
||||||
|
|
||||||
|
lock (this)
|
||||||
{
|
{
|
||||||
switch(GetWorkItemState())
|
switch(GetWorkItemState())
|
||||||
{
|
{
|
||||||
case WorkItemState.Canceled:
|
case WorkItemState.Canceled:
|
||||||
//Debug.WriteLine("Work item already canceled");
|
//Debug.WriteLine("Work item already canceled");
|
||||||
return true;
|
success = true;
|
||||||
|
break;
|
||||||
case WorkItemState.Completed:
|
case WorkItemState.Completed:
|
||||||
case WorkItemState.InProgress:
|
|
||||||
//Debug.WriteLine("Work item cannot be canceled");
|
//Debug.WriteLine("Work item cannot be canceled");
|
||||||
return false;
|
break;
|
||||||
|
case WorkItemState.InProgress:
|
||||||
|
if (abortExecution)
|
||||||
|
{
|
||||||
|
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
||||||
|
if (null != executionThread)
|
||||||
|
{
|
||||||
|
executionThread.Abort("Cancel");
|
||||||
|
success = true;
|
||||||
|
signalComplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
signalComplete = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WorkItemState.InQueue:
|
case WorkItemState.InQueue:
|
||||||
// Signal to the wait for completion that the work
|
// Signal to the wait for completion that the work
|
||||||
// item has been completed (canceled). There is no
|
// item has been completed (canceled). There is no
|
||||||
// reason to wait for it to get out of the queue
|
// reason to wait for it to get out of the queue
|
||||||
SignalComplete(true);
|
signalComplete = true;
|
||||||
//Debug.WriteLine("Work item canceled");
|
//Debug.WriteLine("Work item canceled");
|
||||||
return true;
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalComplete)
|
||||||
|
{
|
||||||
|
SignalComplete(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -651,7 +804,7 @@ namespace Amib.Threading.Internal
|
|||||||
bool exitContext,
|
bool exitContext,
|
||||||
WaitHandle cancelWaitHandle)
|
WaitHandle cancelWaitHandle)
|
||||||
{
|
{
|
||||||
Exception e = null;
|
Exception e;
|
||||||
object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
|
object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
|
||||||
if (null != e)
|
if (null != e)
|
||||||
{
|
{
|
||||||
@@ -704,7 +857,7 @@ namespace Amib.Threading.Internal
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
WaitHandle wh = GetWaitHandle();
|
WaitHandle wh = GetWaitHandle();
|
||||||
int result = WaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
|
int result = EventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
|
||||||
ReleaseWaitHandle();
|
ReleaseWaitHandle();
|
||||||
|
|
||||||
switch(result)
|
switch(result)
|
||||||
@@ -715,7 +868,7 @@ namespace Amib.Threading.Internal
|
|||||||
// work item (not the get result)
|
// work item (not the get result)
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case WaitHandle.WaitTimeout:
|
case EventWaitHandle.WaitTimeout:
|
||||||
throw new WorkItemTimeoutException("Work item timeout");
|
throw new WorkItemTimeoutException("Work item timeout");
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false);
|
Debug.Assert(false);
|
||||||
@@ -747,7 +900,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
if (null == _workItemCompleted)
|
if (null == _workItemCompleted)
|
||||||
{
|
{
|
||||||
_workItemCompleted = new ManualResetEvent(IsCompleted);
|
_workItemCompleted = EventWaitHandleFactory.CreateManualResetEvent(IsCompleted);
|
||||||
}
|
}
|
||||||
++_workItemCompletedRefCount;
|
++_workItemCompletedRefCount;
|
||||||
}
|
}
|
||||||
@@ -844,12 +997,12 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
#region WorkItemResult class
|
#region WorkItemResult class
|
||||||
|
|
||||||
private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult
|
private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult, IInternalWaitableResult
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A back reference to the work item
|
/// A back reference to the work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItem _workItem;
|
private readonly WorkItem _workItem;
|
||||||
|
|
||||||
public WorkItemResult(WorkItem workItem)
|
public WorkItemResult(WorkItem workItem)
|
||||||
{
|
{
|
||||||
@@ -931,7 +1084,12 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
public bool Cancel()
|
public bool Cancel()
|
||||||
{
|
{
|
||||||
return _workItem.Cancel();
|
return Cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Cancel(bool abortExecution)
|
||||||
|
{
|
||||||
|
return _workItem.Cancel(abortExecution);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object State
|
public object State
|
||||||
@@ -997,6 +1155,20 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IInternalWorkItemResult Members
|
||||||
|
|
||||||
|
public IWorkItemResult GetWorkItemResult()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> GetWorkItemResultT<TResult>()
|
||||||
|
{
|
||||||
|
return new WorkItemResultTWrapper<TResult>(this);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
@@ -12,6 +9,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <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="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>
|
||||||
@@ -26,6 +24,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <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="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>
|
||||||
@@ -42,6 +41,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <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>
|
||||||
@@ -63,6 +63,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <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="callback">A callback to execute</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <param name="state">
|
/// <param name="state">
|
||||||
@@ -83,6 +84,7 @@ namespace Amib.Threading.Internal
|
|||||||
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
WorkItem workItem = new WorkItem(
|
||||||
workItemsGroup,
|
workItemsGroup,
|
||||||
@@ -95,6 +97,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <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="state">
|
/// <param name="state">
|
||||||
@@ -131,6 +134,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="workItemInfo">Work item information</param>
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
@@ -160,6 +164,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <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="state">
|
/// <param name="state">
|
||||||
@@ -185,6 +190,7 @@ namespace Amib.Threading.Internal
|
|||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
WorkItem workItem = new WorkItem(
|
||||||
workItemsGroup,
|
workItemsGroup,
|
||||||
@@ -198,6 +204,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <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="state">
|
/// <param name="state">
|
||||||
@@ -239,6 +246,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <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="state">
|
/// <param name="state">
|
||||||
@@ -266,6 +274,7 @@ namespace Amib.Threading.Internal
|
|||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
workItemInfo.CallToPostExecute = callToPostExecute;
|
workItemInfo.CallToPostExecute = callToPostExecute;
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
WorkItem workItem = new WorkItem(
|
||||||
workItemsGroup,
|
workItemsGroup,
|
||||||
@@ -279,6 +288,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new work item
|
/// Create a new work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">The work items group</param>
|
||||||
/// <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="state">
|
/// <param name="state">
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
namespace Amib.Threading
|
namespace Amib.Threading
|
||||||
{
|
{
|
||||||
#region WorkItemInfo class
|
#region WorkItemInfo class
|
||||||
@@ -61,36 +58,54 @@ namespace Amib.Threading
|
|||||||
_workItemPriority = workItemInfo._workItemPriority;
|
_workItemPriority = workItemInfo._workItemPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's security context
|
||||||
|
/// </summary>
|
||||||
public bool UseCallerCallContext
|
public bool UseCallerCallContext
|
||||||
{
|
{
|
||||||
get { return _useCallerCallContext; }
|
get { return _useCallerCallContext; }
|
||||||
set { _useCallerCallContext = value; }
|
set { _useCallerCallContext = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set if to use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
public bool UseCallerHttpContext
|
public bool UseCallerHttpContext
|
||||||
{
|
{
|
||||||
get { return _useCallerHttpContext; }
|
get { return _useCallerHttpContext; }
|
||||||
set { _useCallerHttpContext = value; }
|
set { _useCallerHttpContext = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set if to dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
public bool DisposeOfStateObjects
|
public bool DisposeOfStateObjects
|
||||||
{
|
{
|
||||||
get { return _disposeOfStateObjects; }
|
get { return _disposeOfStateObjects; }
|
||||||
set { _disposeOfStateObjects = value; }
|
set { _disposeOfStateObjects = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the run the post execute options
|
||||||
|
/// </summary>
|
||||||
public CallToPostExecute CallToPostExecute
|
public CallToPostExecute CallToPostExecute
|
||||||
{
|
{
|
||||||
get { return _callToPostExecute; }
|
get { return _callToPostExecute; }
|
||||||
set { _callToPostExecute = value; }
|
set { _callToPostExecute = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the post execute callback
|
||||||
|
/// </summary>
|
||||||
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
{
|
{
|
||||||
get { return _postExecuteWorkItemCallback; }
|
get { return _postExecuteWorkItemCallback; }
|
||||||
set { _postExecuteWorkItemCallback = value; }
|
set { _postExecuteWorkItemCallback = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the work items priority
|
||||||
|
/// </summary>
|
||||||
public WorkItemPriority WorkItemPriority
|
public WorkItemPriority WorkItemPriority
|
||||||
{
|
{
|
||||||
get { return _workItemPriority; }
|
get { return _workItemPriority; }
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
}
|
||||||
+115
-266
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -8,33 +5,34 @@ using System.Diagnostics;
|
|||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
|
|
||||||
#region WorkItemsGroup class
|
#region WorkItemsGroup class
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for WorkItemsGroup.
|
/// Summary description for WorkItemsGroup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WorkItemsGroup : IWorkItemsGroup
|
public class WorkItemsGroup : WorkItemsGroupBase
|
||||||
{
|
{
|
||||||
#region Private members
|
#region Private members
|
||||||
|
|
||||||
private object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
/// <summary>
|
|
||||||
/// Contains the name of this instance of SmartThreadPool.
|
|
||||||
/// Can be changed by the user.
|
|
||||||
/// </summary>
|
|
||||||
private string _name = "WorkItemsGroup";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to the SmartThreadPool instance that created this
|
/// A reference to the SmartThreadPool instance that created this
|
||||||
/// WorkItemsGroup.
|
/// WorkItemsGroup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SmartThreadPool _stp;
|
private readonly SmartThreadPool _stp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The OnIdle event
|
/// The OnIdle event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private event WorkItemsGroupIdleHandler _onIdle;
|
private event WorkItemsGroupIdleHandler _onIdle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A flag to indicate if the Work Items Group is now suspended.
|
||||||
|
/// </summary>
|
||||||
|
private bool _isSuspended;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines how many work items of this WorkItemsGroup can run at once.
|
/// Defines how many work items of this WorkItemsGroup can run at once.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,7 +42,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// Priority queue to hold work items before they are passed
|
/// Priority queue to hold work items before they are passed
|
||||||
/// to the SmartThreadPool.
|
/// to the SmartThreadPool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private PriorityQueue _workItemsQueue;
|
private readonly PriorityQueue _workItemsQueue;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicate how many work items are waiting in the SmartThreadPool
|
/// Indicate how many work items are waiting in the SmartThreadPool
|
||||||
@@ -63,12 +61,13 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// WorkItemsGroup start information
|
/// WorkItemsGroup start information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WIGStartInfo _workItemsGroupStartInfo;
|
private readonly WIGStartInfo _workItemsGroupStartInfo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signaled when all of the WorkItemsGroup's work item completed.
|
/// Signaled when all of the WorkItemsGroup's work item completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
//private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
||||||
|
private readonly ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(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
|
||||||
@@ -87,286 +86,118 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
if (concurrency <= 0)
|
if (concurrency <= 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("concurrency", concurrency, "concurrency must be greater than zero");
|
throw new ArgumentOutOfRangeException(
|
||||||
|
"concurrency",
|
||||||
|
#if !(WindowsCE)
|
||||||
|
concurrency,
|
||||||
|
#endif
|
||||||
|
"concurrency must be greater than zero");
|
||||||
}
|
}
|
||||||
_stp = stp;
|
_stp = stp;
|
||||||
_concurrency = concurrency;
|
_concurrency = concurrency;
|
||||||
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo);
|
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo).AsReadOnly();
|
||||||
_workItemsQueue = new PriorityQueue();
|
_workItemsQueue = new PriorityQueue();
|
||||||
|
Name = "WorkItemsGroup";
|
||||||
|
|
||||||
// The _workItemsInStpQueue gets the number of currently executing work items,
|
// The _workItemsInStpQueue gets the number of currently executing work items,
|
||||||
// because once a work item is executing, it cannot be cancelled.
|
// because once a work item is executing, it cannot be cancelled.
|
||||||
_workItemsInStpQueue = _workItemsExecutingInStp;
|
_workItemsInStpQueue = _workItemsExecutingInStp;
|
||||||
|
|
||||||
|
_isSuspended = _workItemsGroupStartInfo.StartSuspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IWorkItemsGroup implementation
|
#region WorkItemsGroupBase Overrides
|
||||||
|
|
||||||
/// <summary>
|
public override int Concurrency
|
||||||
/// Get/Set the name of the SmartThreadPool instance
|
|
||||||
/// </summary>
|
|
||||||
public string Name
|
|
||||||
{
|
{
|
||||||
get
|
get { return _concurrency; }
|
||||||
{
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_name = value;
|
Debug.Assert(value > 0);
|
||||||
|
|
||||||
|
int diff = value - _concurrency;
|
||||||
|
_concurrency = value;
|
||||||
|
if (diff > 0)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextNWorkItem(diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int WaitingCallbacks
|
||||||
|
{
|
||||||
|
get { return _workItemsQueue.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object[] GetStates()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
object[] states = new object[_workItemsQueue.Count];
|
||||||
|
int i = 0;
|
||||||
|
foreach (WorkItem workItem in _workItemsQueue)
|
||||||
|
{
|
||||||
|
states[i] = workItem.GetWorkItemResult().State;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return states;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queue a work item
|
/// WorkItemsGroup start information
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="callback">A callback to execute</param>
|
public override WIGStartInfo WIGStartInfo
|
||||||
/// <returns>Returns a work item result</returns>
|
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
|
|
||||||
{
|
{
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback);
|
get { return _workItemsGroupStartInfo; }
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queue a work item
|
/// Start the Work Items Group if it was started suspended
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="callback">A callback to execute</param>
|
public override void Start()
|
||||||
/// <param name="workItemPriority">The priority of the work item</param>
|
|
||||||
/// <returns>Returns a work item result</returns>
|
|
||||||
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
|
|
||||||
{
|
{
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, workItemPriority);
|
// If the Work Items Group already started then quit
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
if (!_isSuspended)
|
||||||
return workItem.GetWorkItemResult();
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isSuspended = false;
|
||||||
|
|
||||||
|
EnqueueToSTPNextNWorkItem(_concurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override void Cancel(bool abortExecution)
|
||||||
/// 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)
|
|
||||||
{
|
{
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback);
|
lock (_lock)
|
||||||
EnqueueToSTPNextWorkItem(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, _workItemsGroupStartInfo, callback, state);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, workItemPriority);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback, state);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
|
|
||||||
EnqueueToSTPNextWorkItem(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)
|
|
||||||
{
|
|
||||||
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
|
|
||||||
EnqueueToSTPNextWorkItem(workItem);
|
|
||||||
return workItem.GetWorkItemResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wait for the thread pool to be idle
|
|
||||||
/// </summary>
|
|
||||||
public void WaitForIdle()
|
|
||||||
{
|
|
||||||
WaitForIdle(Timeout.Infinite);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wait for the thread pool to be idle
|
|
||||||
/// </summary>
|
|
||||||
public bool WaitForIdle(TimeSpan timeout)
|
|
||||||
{
|
|
||||||
return WaitForIdle((int)timeout.TotalMilliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wait for the thread pool to be idle
|
|
||||||
/// </summary>
|
|
||||||
public bool WaitForIdle(int millisecondsTimeout)
|
|
||||||
{
|
|
||||||
_stp.ValidateWorkItemsGroupWaitForIdle(this);
|
|
||||||
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int WaitingCallbacks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _workItemsQueue.Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public event WorkItemsGroupIdleHandler OnIdle
|
|
||||||
{
|
|
||||||
add
|
|
||||||
{
|
|
||||||
_onIdle += value;
|
|
||||||
}
|
|
||||||
remove
|
|
||||||
{
|
|
||||||
_onIdle -= value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Cancel()
|
|
||||||
{
|
|
||||||
lock(_lock)
|
|
||||||
{
|
{
|
||||||
_canceledWorkItemsGroup.IsCanceled = true;
|
_canceledWorkItemsGroup.IsCanceled = true;
|
||||||
_workItemsQueue.Clear();
|
_workItemsQueue.Clear();
|
||||||
_workItemsInStpQueue = 0;
|
_workItemsInStpQueue = 0;
|
||||||
_canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
_canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abortExecution)
|
||||||
|
{
|
||||||
|
_stp.CancelAbortWorkItemsGroup(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
/// <summary>
|
||||||
|
/// Wait for the thread pool to be idle
|
||||||
|
/// </summary>
|
||||||
|
public override bool WaitForIdle(int millisecondsTimeout)
|
||||||
{
|
{
|
||||||
lock (this)
|
SmartThreadPool.ValidateWorkItemsGroupWaitForIdle(this);
|
||||||
{
|
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
||||||
if (!_workItemsGroupStartInfo.StartSuspended)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_workItemsGroupStartInfo.StartSuspended = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < _concurrency; ++i)
|
public override event WorkItemsGroupIdleHandler OnIdle
|
||||||
{
|
{
|
||||||
EnqueueToSTPNextWorkItem(null, false);
|
add { _onIdle += value; }
|
||||||
}
|
remove { _onIdle -= value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -375,22 +206,24 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
|
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
|
||||||
{
|
{
|
||||||
IInternalWorkItemResult iwir = wir as IInternalWorkItemResult;
|
IInternalWorkItemResult iwir = (IInternalWorkItemResult)wir;
|
||||||
iwir.OnWorkItemStarted += new WorkItemStateCallback(OnWorkItemStartedCallback);
|
iwir.OnWorkItemStarted += OnWorkItemStartedCallback;
|
||||||
iwir.OnWorkItemCompleted += new WorkItemStateCallback(OnWorkItemCompletedCallback);
|
iwir.OnWorkItemCompleted += OnWorkItemCompletedCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnSTPIsStarting()
|
public void OnSTPIsStarting()
|
||||||
{
|
{
|
||||||
lock (this)
|
if (_isSuspended)
|
||||||
{
|
|
||||||
if (_workItemsGroupStartInfo.StartSuspended)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnqueueToSTPNextNWorkItem(_concurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < _concurrency; ++i)
|
public void EnqueueToSTPNextNWorkItem(int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
EnqueueToSTPNextWorkItem(null, false);
|
EnqueueToSTPNextWorkItem(null, false);
|
||||||
}
|
}
|
||||||
@@ -417,8 +250,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
eh(this);
|
eh(this);
|
||||||
}
|
}
|
||||||
// Ignore exceptions
|
catch { } // Suppress exceptions
|
||||||
catch{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,6 +267,11 @@ namespace Amib.Threading.Internal
|
|||||||
EnqueueToSTPNextWorkItem(null, true);
|
EnqueueToSTPNextWorkItem(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal override void Enqueue(WorkItem workItem)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
}
|
||||||
|
|
||||||
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
|
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
|
||||||
{
|
{
|
||||||
EnqueueToSTPNextWorkItem(workItem, false);
|
EnqueueToSTPNextWorkItem(workItem, false);
|
||||||
@@ -475,7 +312,7 @@ namespace Amib.Threading.Internal
|
|||||||
(0 == _workItemsInStpQueue))
|
(0 == _workItemsInStpQueue))
|
||||||
{
|
{
|
||||||
_stp.RegisterWorkItemsGroup(this);
|
_stp.RegisterWorkItemsGroup(this);
|
||||||
Trace.WriteLine("WorkItemsGroup " + Name + " is NOT idle");
|
IsIdle = false;
|
||||||
_isIdleWaitHandle.Reset();
|
_isIdleWaitHandle.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,19 +323,31 @@ namespace Amib.Threading.Internal
|
|||||||
if (0 == _workItemsInStpQueue)
|
if (0 == _workItemsInStpQueue)
|
||||||
{
|
{
|
||||||
_stp.UnregisterWorkItemsGroup(this);
|
_stp.UnregisterWorkItemsGroup(this);
|
||||||
Trace.WriteLine("WorkItemsGroup " + Name + " is idle");
|
IsIdle = true;
|
||||||
_isIdleWaitHandle.Set();
|
_isIdleWaitHandle.Set();
|
||||||
_stp.QueueWorkItem(new WorkItemCallback(this.FireOnIdle));
|
if (decrementWorkItemsInStpQueue)
|
||||||
|
{
|
||||||
|
_stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_workItemsGroupStartInfo.StartSuspended)
|
if (!_isSuspended)
|
||||||
{
|
{
|
||||||
if (_workItemsInStpQueue < _concurrency)
|
if (_workItemsInStpQueue < _concurrency)
|
||||||
{
|
{
|
||||||
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
|
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
|
||||||
_stp.Enqueue(nextWorkItem, true);
|
try
|
||||||
|
{
|
||||||
|
_stp.Enqueue(nextWorkItem);
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException e)
|
||||||
|
{
|
||||||
|
e.GetHashCode();
|
||||||
|
// The STP has been shutdown
|
||||||
|
}
|
||||||
|
|
||||||
++_workItemsInStpQueue;
|
++_workItemsInStpQueue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,448 @@
|
|||||||
|
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";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inidcates if the SmartThreadPool/WorkItemsGroup is idle.
|
||||||
|
/// Its value is true if the _isIdleWaitHandle is set.
|
||||||
|
/// </summary>
|
||||||
|
private bool _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 { return _isIdle; }
|
||||||
|
protected set { _isIdle = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T>(Action<T> action, T arg)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke(arg);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke(arg1, arg2);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke(arg1, arg2, arg3);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
action.Invoke(arg1, arg2, arg3, arg4);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null);
|
||||||
|
Enqueue(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region QueueWorkItem(Func<...>)
|
||||||
|
|
||||||
|
public IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func)
|
||||||
|
{
|
||||||
|
PreQueueWorkItem();
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(
|
||||||
|
this,
|
||||||
|
WIGStartInfo,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
// Ami Bar
|
|
||||||
// amibar@gmail.com
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -18,7 +15,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waiters queue (implemented as stack).
|
/// Waiters queue (implemented as stack).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WaiterEntry _headWaiterEntry = new WaiterEntry();
|
private readonly WaiterEntry _headWaiterEntry = new WaiterEntry();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waiters count
|
/// Waiters count
|
||||||
@@ -28,18 +25,48 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work items queue
|
/// Work items queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private PriorityQueue _workItems = new PriorityQueue();
|
private readonly PriorityQueue _workItems = new PriorityQueue();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicate that work items are allowed to be queued
|
/// Indicate that work items are allowed to be queued
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _isWorkItemsQueueActive = true;
|
private bool _isWorkItemsQueueActive = true;
|
||||||
|
|
||||||
|
|
||||||
|
#if (WindowsCE)
|
||||||
|
private static LocalDataStoreSlot _waiterEntrySlot = Thread.AllocateDataSlot();
|
||||||
|
#else
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static WaiterEntry _waiterEntry;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Each thread in the thread pool keeps its own waiter entry.
|
/// Each thread in the thread pool keeps its own waiter entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ThreadStatic]
|
private static WaiterEntry CurrentWaiterEntry
|
||||||
private static WaiterEntry _waiterEntry;
|
{
|
||||||
|
#if (WindowsCE)
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Thread.GetData(_waiterEntrySlot) as WaiterEntry;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Thread.SetData(_waiterEntrySlot, value);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _waiterEntry;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_waiterEntry = value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A flag that indicates if the WorkItemsQueue has been disposed.
|
/// A flag that indicates if the WorkItemsQueue has been disposed.
|
||||||
@@ -57,13 +84,9 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
lock(this)
|
|
||||||
{
|
|
||||||
ValidateNotDisposed();
|
|
||||||
return _workItems.Count;
|
return _workItems.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the current number of waiters
|
/// Returns the current number of waiters
|
||||||
@@ -72,13 +95,9 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
lock(this)
|
|
||||||
{
|
|
||||||
ValidateNotDisposed();
|
|
||||||
return _waitersCount;
|
return _waitersCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -144,19 +163,19 @@ namespace Amib.Threading.Internal
|
|||||||
int millisecondsTimeout,
|
int millisecondsTimeout,
|
||||||
WaitHandle cancelEvent)
|
WaitHandle cancelEvent)
|
||||||
{
|
{
|
||||||
/// This method cause the caller to wait for a work item.
|
// This method cause the caller to wait for a work item.
|
||||||
/// If there is at least one waiting work item then the
|
// If there is at least one waiting work item then the
|
||||||
/// method returns immidiately with true.
|
// method returns immidiately with true.
|
||||||
///
|
//
|
||||||
/// If there are no waiting work items then the caller
|
// If there are no waiting work items then the caller
|
||||||
/// is queued between other waiters for a work item to arrive.
|
// is queued between other waiters for a work item to arrive.
|
||||||
///
|
//
|
||||||
/// If a work item didn't come within millisecondsTimeout or
|
// If a work item didn't come within millisecondsTimeout or
|
||||||
/// the user canceled the wait by signaling the cancelEvent
|
// the user canceled the wait by signaling the cancelEvent
|
||||||
/// then the method returns false to indicate that the caller
|
// then the method returns false to indicate that the caller
|
||||||
/// didn't get a work item.
|
// didn't get a work item.
|
||||||
|
|
||||||
WaiterEntry waiterEntry = null;
|
WaiterEntry waiterEntry;
|
||||||
WorkItem workItem = null;
|
WorkItem workItem = null;
|
||||||
|
|
||||||
lock(this)
|
lock(this)
|
||||||
@@ -169,19 +188,18 @@ namespace Amib.Threading.Internal
|
|||||||
workItem = _workItems.Dequeue() as WorkItem;
|
workItem = _workItems.Dequeue() as WorkItem;
|
||||||
return workItem;
|
return workItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No waiting work items ...
|
// No waiting work items ...
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get the wait entry for the waiters queue
|
// Get the wait entry for the waiters queue
|
||||||
waiterEntry = GetThreadWaiterEntry();
|
waiterEntry = GetThreadWaiterEntry();
|
||||||
|
|
||||||
// Put the waiter with the other waiters
|
// Put the waiter with the other waiters
|
||||||
PushWaiter(waiterEntry);
|
PushWaiter(waiterEntry);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare array of wait handle for the WaitHandle.WaitAny()
|
// Prepare array of wait handle for the WaitHandle.WaitAny()
|
||||||
WaitHandle [] waitHandles = new WaitHandle [] {
|
WaitHandle [] waitHandles = new WaitHandle[] {
|
||||||
waiterEntry.WaitHandle,
|
waiterEntry.WaitHandle,
|
||||||
cancelEvent };
|
cancelEvent };
|
||||||
|
|
||||||
@@ -189,10 +207,10 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
// During the wait we are supposes to exit the synchronization
|
// During the wait we are supposes to exit the synchronization
|
||||||
// domain. (Placing true as the third argument of the WaitAny())
|
// domain. (Placing true as the third argument of the WaitAny())
|
||||||
// It just doesn't work, I don't know why, so I have lock(this)
|
// It just doesn't work, I don't know why, so I have two lock(this)
|
||||||
// statments insted of one.
|
// statments insted of one.
|
||||||
|
|
||||||
int index = WaitHandle.WaitAny(
|
int index = EventWaitHandle.WaitAny(
|
||||||
waitHandles,
|
waitHandles,
|
||||||
millisecondsTimeout,
|
millisecondsTimeout,
|
||||||
true);
|
true);
|
||||||
@@ -242,7 +260,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// Cleanup the work items queue, hence no more work
|
/// Cleanup the work items queue, hence no more work
|
||||||
/// items are allowed to be queue
|
/// items are allowed to be queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void Cleanup()
|
private void Cleanup()
|
||||||
{
|
{
|
||||||
lock(this)
|
lock(this)
|
||||||
{
|
{
|
||||||
@@ -279,6 +297,21 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object[] GetStates()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
object[] states = new object[_workItems.Count];
|
||||||
|
int i = 0;
|
||||||
|
foreach (WorkItem workItem in _workItems)
|
||||||
|
{
|
||||||
|
states[i] = workItem.GetWorkItemResult().State;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private methods
|
#region Private methods
|
||||||
@@ -289,14 +322,14 @@ namespace Amib.Threading.Internal
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// In order to avoid creation and destuction of WaiterEntry
|
/// In order to avoid creation and destuction of WaiterEntry
|
||||||
/// objects each thread has its own WaiterEntry object.
|
/// objects each thread has its own WaiterEntry object.
|
||||||
private WaiterEntry GetThreadWaiterEntry()
|
private static WaiterEntry GetThreadWaiterEntry()
|
||||||
{
|
{
|
||||||
if (null == _waiterEntry)
|
if (null == CurrentWaiterEntry)
|
||||||
{
|
{
|
||||||
_waiterEntry = new WaiterEntry();
|
CurrentWaiterEntry = new WaiterEntry();
|
||||||
}
|
}
|
||||||
_waiterEntry.Reset();
|
CurrentWaiterEntry.Reset();
|
||||||
return _waiterEntry;
|
return CurrentWaiterEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Waiters stack methods
|
#region Waiters stack methods
|
||||||
@@ -418,14 +451,15 @@ namespace Amib.Threading.Internal
|
|||||||
#region WaiterEntry class
|
#region WaiterEntry class
|
||||||
|
|
||||||
// A waiter entry in the _waiters queue.
|
// A waiter entry in the _waiters queue.
|
||||||
public class WaiterEntry : IDisposable
|
public sealed class WaiterEntry : IDisposable
|
||||||
{
|
{
|
||||||
#region Member variables
|
#region Member variables
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event to signal the waiter that it got the work item.
|
/// Event to signal the waiter that it got the work item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
|
//private AutoResetEvent _waitHandle = new AutoResetEvent(false);
|
||||||
|
private AutoResetEvent _waitHandle = EventWaitHandleFactory.CreateAutoResetEvent();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag to know if this waiter already quited from the queue
|
/// Flag to know if this waiter already quited from the queue
|
||||||
@@ -550,18 +584,16 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
if (!_isDisposed)
|
if (!_isDisposed)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
|
}
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~WaiterEntry()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,14 +606,8 @@ namespace Amib.Threading.Internal
|
|||||||
if (!_isDisposed)
|
if (!_isDisposed)
|
||||||
{
|
{
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
}
|
||||||
_isDisposed = true;
|
_isDisposed = true;
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~WorkItemsQueue()
|
|
||||||
{
|
|
||||||
Cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateNotDisposed()
|
private void ValidateNotDisposed()
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ namespace TestSmartThreadPool
|
|||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.components = new System.ComponentModel.Container();
|
this.components = new System.ComponentModel.Container();
|
||||||
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||||
this.btnStart = new System.Windows.Forms.Button();
|
this.btnStart = new System.Windows.Forms.Button();
|
||||||
this.btnStop = new System.Windows.Forms.Button();
|
this.btnStop = new System.Windows.Forms.Button();
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
@@ -136,7 +136,7 @@ namespace TestSmartThreadPool
|
|||||||
// btnStart
|
// btnStart
|
||||||
//
|
//
|
||||||
this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.btnStart.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.btnStart.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.btnStart.Location = new System.Drawing.Point(432, 352);
|
this.btnStart.Location = new System.Drawing.Point(432, 352);
|
||||||
this.btnStart.Name = "btnStart";
|
this.btnStart.Name = "btnStart";
|
||||||
this.btnStart.Size = new System.Drawing.Size(72, 24);
|
this.btnStart.Size = new System.Drawing.Size(72, 24);
|
||||||
@@ -147,7 +147,7 @@ namespace TestSmartThreadPool
|
|||||||
// btnStop
|
// btnStop
|
||||||
//
|
//
|
||||||
this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
this.btnStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.btnStop.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.btnStop.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.btnStop.Location = new System.Drawing.Point(520, 352);
|
this.btnStop.Location = new System.Drawing.Point(520, 352);
|
||||||
this.btnStop.Name = "btnStop";
|
this.btnStop.Name = "btnStop";
|
||||||
this.btnStop.Size = new System.Drawing.Size(72, 24);
|
this.btnStop.Size = new System.Drawing.Size(72, 24);
|
||||||
@@ -158,7 +158,7 @@ namespace TestSmartThreadPool
|
|||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label1.Location = new System.Drawing.Point(104, 256);
|
this.label1.Location = new System.Drawing.Point(104, 256);
|
||||||
this.label1.Name = "label1";
|
this.label1.Name = "label1";
|
||||||
this.label1.Size = new System.Drawing.Size(104, 24);
|
this.label1.Size = new System.Drawing.Size(104, 24);
|
||||||
@@ -169,7 +169,7 @@ namespace TestSmartThreadPool
|
|||||||
// label3
|
// label3
|
||||||
//
|
//
|
||||||
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label3.Location = new System.Drawing.Point(104, 288);
|
this.label3.Location = new System.Drawing.Point(104, 288);
|
||||||
this.label3.Name = "label3";
|
this.label3.Name = "label3";
|
||||||
this.label3.Size = new System.Drawing.Size(104, 24);
|
this.label3.Size = new System.Drawing.Size(104, 24);
|
||||||
@@ -180,17 +180,18 @@ namespace TestSmartThreadPool
|
|||||||
// label4
|
// label4
|
||||||
//
|
//
|
||||||
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label4.Location = new System.Drawing.Point(104, 320);
|
this.label4.Location = new System.Drawing.Point(104, 320);
|
||||||
this.label4.Name = "label4";
|
this.label4.Name = "label4";
|
||||||
this.label4.Size = new System.Drawing.Size(120, 24);
|
this.label4.Size = new System.Drawing.Size(120, 24);
|
||||||
this.label4.TabIndex = 5;
|
this.label4.TabIndex = 5;
|
||||||
this.label4.Text = "Idle timeout (Seconds)";
|
this.label4.Text = "Idle timeout (Seconds)";
|
||||||
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||||
|
this.label4.Click += new System.EventHandler(this.label4_Click);
|
||||||
//
|
//
|
||||||
// label2
|
// label2
|
||||||
//
|
//
|
||||||
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label2.Location = new System.Drawing.Point(8, 16);
|
this.label2.Location = new System.Drawing.Point(8, 16);
|
||||||
this.label2.Name = "label2";
|
this.label2.Name = "label2";
|
||||||
this.label2.Size = new System.Drawing.Size(72, 24);
|
this.label2.Size = new System.Drawing.Size(72, 24);
|
||||||
@@ -200,7 +201,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// lblThreadsInPool
|
// lblThreadsInPool
|
||||||
//
|
//
|
||||||
this.lblThreadsInPool.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.lblThreadsInPool.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.lblThreadsInPool.Location = new System.Drawing.Point(80, 16);
|
this.lblThreadsInPool.Location = new System.Drawing.Point(80, 16);
|
||||||
this.lblThreadsInPool.Name = "lblThreadsInPool";
|
this.lblThreadsInPool.Name = "lblThreadsInPool";
|
||||||
this.lblThreadsInPool.Size = new System.Drawing.Size(80, 24);
|
this.lblThreadsInPool.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -211,7 +212,7 @@ namespace TestSmartThreadPool
|
|||||||
// label5
|
// label5
|
||||||
//
|
//
|
||||||
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label5.Location = new System.Drawing.Point(336, 258);
|
this.label5.Location = new System.Drawing.Point(336, 258);
|
||||||
this.label5.Name = "label5";
|
this.label5.Name = "label5";
|
||||||
this.label5.Size = new System.Drawing.Size(280, 24);
|
this.label5.Size = new System.Drawing.Size(280, 24);
|
||||||
@@ -222,9 +223,9 @@ namespace TestSmartThreadPool
|
|||||||
// spinIdleTimeout
|
// spinIdleTimeout
|
||||||
//
|
//
|
||||||
this.spinIdleTimeout.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.spinIdleTimeout.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.spinIdleTimeout.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.spinIdleTimeout.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.spinIdleTimeout.Location = new System.Drawing.Point(8, 320);
|
this.spinIdleTimeout.Location = new System.Drawing.Point(8, 320);
|
||||||
this.spinIdleTimeout.Minimum = new System.Decimal(new int[] {
|
this.spinIdleTimeout.Minimum = new decimal(new int[] {
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -233,7 +234,7 @@ namespace TestSmartThreadPool
|
|||||||
this.spinIdleTimeout.Size = new System.Drawing.Size(88, 29);
|
this.spinIdleTimeout.Size = new System.Drawing.Size(88, 29);
|
||||||
this.spinIdleTimeout.TabIndex = 15;
|
this.spinIdleTimeout.TabIndex = 15;
|
||||||
this.spinIdleTimeout.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.spinIdleTimeout.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
this.spinIdleTimeout.Value = new System.Decimal(new int[] {
|
this.spinIdleTimeout.Value = new decimal(new int[] {
|
||||||
10,
|
10,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -242,9 +243,9 @@ namespace TestSmartThreadPool
|
|||||||
// spinMaxThreads
|
// spinMaxThreads
|
||||||
//
|
//
|
||||||
this.spinMaxThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.spinMaxThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.spinMaxThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.spinMaxThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.spinMaxThreads.Location = new System.Drawing.Point(8, 288);
|
this.spinMaxThreads.Location = new System.Drawing.Point(8, 288);
|
||||||
this.spinMaxThreads.Minimum = new System.Decimal(new int[] {
|
this.spinMaxThreads.Minimum = new decimal(new int[] {
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -253,7 +254,7 @@ namespace TestSmartThreadPool
|
|||||||
this.spinMaxThreads.Size = new System.Drawing.Size(88, 29);
|
this.spinMaxThreads.Size = new System.Drawing.Size(88, 29);
|
||||||
this.spinMaxThreads.TabIndex = 14;
|
this.spinMaxThreads.TabIndex = 14;
|
||||||
this.spinMaxThreads.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.spinMaxThreads.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
this.spinMaxThreads.Value = new System.Decimal(new int[] {
|
this.spinMaxThreads.Value = new decimal(new int[] {
|
||||||
10,
|
10,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -263,7 +264,7 @@ namespace TestSmartThreadPool
|
|||||||
// spinMinThreads
|
// spinMinThreads
|
||||||
//
|
//
|
||||||
this.spinMinThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.spinMinThreads.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.spinMinThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.spinMinThreads.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.spinMinThreads.Location = new System.Drawing.Point(8, 256);
|
this.spinMinThreads.Location = new System.Drawing.Point(8, 256);
|
||||||
this.spinMinThreads.Name = "spinMinThreads";
|
this.spinMinThreads.Name = "spinMinThreads";
|
||||||
this.spinMinThreads.Size = new System.Drawing.Size(88, 29);
|
this.spinMinThreads.Size = new System.Drawing.Size(88, 29);
|
||||||
@@ -274,14 +275,14 @@ namespace TestSmartThreadPool
|
|||||||
// spinInterval
|
// spinInterval
|
||||||
//
|
//
|
||||||
this.spinInterval.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.spinInterval.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.spinInterval.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.spinInterval.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.spinInterval.Increment = new System.Decimal(new int[] {
|
this.spinInterval.Increment = new decimal(new int[] {
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
this.spinInterval.Location = new System.Drawing.Point(240, 256);
|
this.spinInterval.Location = new System.Drawing.Point(240, 256);
|
||||||
this.spinInterval.Maximum = new System.Decimal(new int[] {
|
this.spinInterval.Maximum = new decimal(new int[] {
|
||||||
100000,
|
100000,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -290,7 +291,7 @@ namespace TestSmartThreadPool
|
|||||||
this.spinInterval.Size = new System.Drawing.Size(88, 29);
|
this.spinInterval.Size = new System.Drawing.Size(88, 29);
|
||||||
this.spinInterval.TabIndex = 16;
|
this.spinInterval.TabIndex = 16;
|
||||||
this.spinInterval.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.spinInterval.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
this.spinInterval.Value = new System.Decimal(new int[] {
|
this.spinInterval.Value = new decimal(new int[] {
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -298,7 +299,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// lblThreadInUse
|
// lblThreadInUse
|
||||||
//
|
//
|
||||||
this.lblThreadInUse.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.lblThreadInUse.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.lblThreadInUse.Location = new System.Drawing.Point(80, 40);
|
this.lblThreadInUse.Location = new System.Drawing.Point(80, 40);
|
||||||
this.lblThreadInUse.Name = "lblThreadInUse";
|
this.lblThreadInUse.Name = "lblThreadInUse";
|
||||||
this.lblThreadInUse.Size = new System.Drawing.Size(80, 24);
|
this.lblThreadInUse.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -308,7 +309,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// label7
|
// label7
|
||||||
//
|
//
|
||||||
this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label7.Location = new System.Drawing.Point(8, 40);
|
this.label7.Location = new System.Drawing.Point(8, 40);
|
||||||
this.label7.Name = "label7";
|
this.label7.Name = "label7";
|
||||||
this.label7.Size = new System.Drawing.Size(80, 24);
|
this.label7.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -324,14 +325,14 @@ namespace TestSmartThreadPool
|
|||||||
// spinConsumingTime
|
// spinConsumingTime
|
||||||
//
|
//
|
||||||
this.spinConsumingTime.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.spinConsumingTime.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.spinConsumingTime.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.spinConsumingTime.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.spinConsumingTime.Increment = new System.Decimal(new int[] {
|
this.spinConsumingTime.Increment = new decimal(new int[] {
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0});
|
0});
|
||||||
this.spinConsumingTime.Location = new System.Drawing.Point(240, 288);
|
this.spinConsumingTime.Location = new System.Drawing.Point(240, 288);
|
||||||
this.spinConsumingTime.Maximum = new System.Decimal(new int[] {
|
this.spinConsumingTime.Maximum = new decimal(new int[] {
|
||||||
100000,
|
100000,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -340,7 +341,7 @@ namespace TestSmartThreadPool
|
|||||||
this.spinConsumingTime.Size = new System.Drawing.Size(88, 29);
|
this.spinConsumingTime.Size = new System.Drawing.Size(88, 29);
|
||||||
this.spinConsumingTime.TabIndex = 20;
|
this.spinConsumingTime.TabIndex = 20;
|
||||||
this.spinConsumingTime.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
this.spinConsumingTime.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||||
this.spinConsumingTime.Value = new System.Decimal(new int[] {
|
this.spinConsumingTime.Value = new decimal(new int[] {
|
||||||
100,
|
100,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -349,7 +350,7 @@ namespace TestSmartThreadPool
|
|||||||
// label6
|
// label6
|
||||||
//
|
//
|
||||||
this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
this.label6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||||
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label6.Location = new System.Drawing.Point(336, 290);
|
this.label6.Location = new System.Drawing.Point(336, 290);
|
||||||
this.label6.Name = "label6";
|
this.label6.Name = "label6";
|
||||||
this.label6.Size = new System.Drawing.Size(216, 24);
|
this.label6.Size = new System.Drawing.Size(216, 24);
|
||||||
@@ -359,7 +360,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// lblWaitingCallbacks
|
// lblWaitingCallbacks
|
||||||
//
|
//
|
||||||
this.lblWaitingCallbacks.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.lblWaitingCallbacks.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.lblWaitingCallbacks.Location = new System.Drawing.Point(64, 16);
|
this.lblWaitingCallbacks.Location = new System.Drawing.Point(64, 16);
|
||||||
this.lblWaitingCallbacks.Name = "lblWaitingCallbacks";
|
this.lblWaitingCallbacks.Name = "lblWaitingCallbacks";
|
||||||
this.lblWaitingCallbacks.Size = new System.Drawing.Size(80, 24);
|
this.lblWaitingCallbacks.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -369,7 +370,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// label9
|
// label9
|
||||||
//
|
//
|
||||||
this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label9.Location = new System.Drawing.Point(8, 16);
|
this.label9.Location = new System.Drawing.Point(8, 16);
|
||||||
this.label9.Name = "label9";
|
this.label9.Name = "label9";
|
||||||
this.label9.Size = new System.Drawing.Size(48, 24);
|
this.label9.Size = new System.Drawing.Size(48, 24);
|
||||||
@@ -379,7 +380,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// label8
|
// label8
|
||||||
//
|
//
|
||||||
this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label8.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label8.Location = new System.Drawing.Point(8, 40);
|
this.label8.Location = new System.Drawing.Point(8, 40);
|
||||||
this.label8.Name = "label8";
|
this.label8.Name = "label8";
|
||||||
this.label8.Size = new System.Drawing.Size(64, 24);
|
this.label8.Size = new System.Drawing.Size(64, 24);
|
||||||
@@ -389,7 +390,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// label10
|
// label10
|
||||||
//
|
//
|
||||||
this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.label10.Location = new System.Drawing.Point(8, 64);
|
this.label10.Location = new System.Drawing.Point(8, 64);
|
||||||
this.label10.Name = "label10";
|
this.label10.Name = "label10";
|
||||||
this.label10.Size = new System.Drawing.Size(64, 24);
|
this.label10.Size = new System.Drawing.Size(64, 24);
|
||||||
@@ -399,7 +400,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// lblWorkItemsGenerated
|
// lblWorkItemsGenerated
|
||||||
//
|
//
|
||||||
this.lblWorkItemsGenerated.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.lblWorkItemsGenerated.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.lblWorkItemsGenerated.Location = new System.Drawing.Point(64, 40);
|
this.lblWorkItemsGenerated.Location = new System.Drawing.Point(64, 40);
|
||||||
this.lblWorkItemsGenerated.Name = "lblWorkItemsGenerated";
|
this.lblWorkItemsGenerated.Name = "lblWorkItemsGenerated";
|
||||||
this.lblWorkItemsGenerated.Size = new System.Drawing.Size(80, 24);
|
this.lblWorkItemsGenerated.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -409,7 +410,7 @@ namespace TestSmartThreadPool
|
|||||||
//
|
//
|
||||||
// lblWorkItemsCompleted
|
// lblWorkItemsCompleted
|
||||||
//
|
//
|
||||||
this.lblWorkItemsCompleted.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.lblWorkItemsCompleted.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.lblWorkItemsCompleted.Location = new System.Drawing.Point(64, 64);
|
this.lblWorkItemsCompleted.Location = new System.Drawing.Point(64, 64);
|
||||||
this.lblWorkItemsCompleted.Name = "lblWorkItemsCompleted";
|
this.lblWorkItemsCompleted.Name = "lblWorkItemsCompleted";
|
||||||
this.lblWorkItemsCompleted.Size = new System.Drawing.Size(80, 24);
|
this.lblWorkItemsCompleted.Size = new System.Drawing.Size(80, 24);
|
||||||
@@ -542,7 +543,7 @@ namespace TestSmartThreadPool
|
|||||||
this.Controls.Add(this.label1);
|
this.Controls.Add(this.label1);
|
||||||
this.Controls.Add(this.btnStop);
|
this.Controls.Add(this.btnStop);
|
||||||
this.Controls.Add(this.btnStart);
|
this.Controls.Add(this.btnStart);
|
||||||
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
|
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
this.MinimumSize = new System.Drawing.Size(616, 416);
|
this.MinimumSize = new System.Drawing.Size(616, 416);
|
||||||
this.Name = "Form1";
|
this.Name = "Form1";
|
||||||
@@ -579,6 +580,7 @@ namespace TestSmartThreadPool
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
|
||||||
Application.Run(new Form1());
|
Application.Run(new Form1());
|
||||||
}
|
}
|
||||||
@@ -586,7 +588,7 @@ namespace TestSmartThreadPool
|
|||||||
// This method is a work around for the Peformance Counter issue.
|
// This method is a work around for the Peformance Counter issue.
|
||||||
// When the first SmartThreadPool is created with a Peformance
|
// When the first SmartThreadPool is created with a Peformance
|
||||||
// Counter name on a machine, it creates the SmartThreadPool
|
// Counter name on a machine, it creates the SmartThreadPool
|
||||||
// Peformance Counter category. In this demo I use thes Performance
|
// Peformance Counter category. In this demo I am using the Performance
|
||||||
// Counters to update the GUI.
|
// Counters to update the GUI.
|
||||||
// The issue is that if this demo runs for the first time on the
|
// The issue is that if this demo runs for the first time on the
|
||||||
// machine, it creates the Peformance Counter category and then
|
// machine, it creates the Peformance Counter category and then
|
||||||
@@ -666,7 +668,7 @@ namespace TestSmartThreadPool
|
|||||||
running = false;
|
running = false;
|
||||||
workItemsProducerThread.Join();
|
workItemsProducerThread.Join();
|
||||||
|
|
||||||
_smartThreadPool.Shutdown();
|
_smartThreadPool.Shutdown(true, 1000);
|
||||||
_smartThreadPool.Dispose();
|
_smartThreadPool.Dispose();
|
||||||
_smartThreadPool = null;
|
_smartThreadPool = null;
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
@@ -682,8 +684,8 @@ namespace TestSmartThreadPool
|
|||||||
private void UpdateControls(bool start)
|
private void UpdateControls(bool start)
|
||||||
{
|
{
|
||||||
running = start;
|
running = start;
|
||||||
spinMinThreads.Enabled = !start;
|
//spinMinThreads.Enabled = !start;
|
||||||
spinMaxThreads.Enabled = !start;
|
//spinMaxThreads.Enabled = !start;
|
||||||
spinIdleTimeout.Enabled = !start;
|
spinIdleTimeout.Enabled = !start;
|
||||||
btnStart.Enabled = !start;
|
btnStart.Enabled = !start;
|
||||||
|
|
||||||
@@ -708,6 +710,11 @@ namespace TestSmartThreadPool
|
|||||||
{
|
{
|
||||||
spinMaxThreads.Value = spinMinThreads.Value;
|
spinMaxThreads.Value = spinMinThreads.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null != _smartThreadPool)
|
||||||
|
{
|
||||||
|
_smartThreadPool.MinThreads = (int)spinMinThreads.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void spinMaxThreads_ValueChanged(object sender, System.EventArgs e)
|
private void spinMaxThreads_ValueChanged(object sender, System.EventArgs e)
|
||||||
@@ -717,6 +724,10 @@ namespace TestSmartThreadPool
|
|||||||
spinMinThreads.Value = spinMaxThreads.Value;
|
spinMinThreads.Value = spinMaxThreads.Value;
|
||||||
}
|
}
|
||||||
usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
usageThreadsInPool.Maximum = Convert.ToInt32(spinMaxThreads.Value);
|
||||||
|
if (null != _smartThreadPool)
|
||||||
|
{
|
||||||
|
_smartThreadPool.MaxThreads = (int)spinMaxThreads.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void timer1_Tick(object sender, System.EventArgs e)
|
private void timer1_Tick(object sender, System.EventArgs e)
|
||||||
@@ -777,10 +788,15 @@ namespace TestSmartThreadPool
|
|||||||
{
|
{
|
||||||
if (null != _smartThreadPool)
|
if (null != _smartThreadPool)
|
||||||
{
|
{
|
||||||
_smartThreadPool.Shutdown();
|
_smartThreadPool.Shutdown(true, 1000);
|
||||||
_smartThreadPool = null;
|
_smartThreadPool = null;
|
||||||
_workItemsGroup = null;
|
_workItemsGroup = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void label4_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-370
@@ -3,7 +3,7 @@
|
|||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
|
|
||||||
Version 1.3
|
Version 2.0
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
The primary goals of this format is to allow a simple XML format
|
||||||
that is mostly human readable. The generation and parsing of the
|
that is mostly human readable. The generation and parsing of the
|
||||||
@@ -14,16 +14,17 @@
|
|||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
... ado.net/XML headers & schema ...
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
<resheader name="version">1.3</resheader>
|
<resheader name="version">2.0</resheader>
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
<data name="Name1">this is my long string</data>
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
[base64 mime encoded serialized .NET Framework object]
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
There are any number of "resheader" rows that contain simple
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
Classes that don't support this are serialized and stored with the
|
Classes that don't support this are serialized and stored with the
|
||||||
mimetype set.
|
mimetype set.
|
||||||
|
|
||||||
The mimetype is used forserialized objects, and tells the
|
The mimetype is used for serialized objects, and tells the
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
value : The object must be serialized with
|
value : The object must be serialized with
|
||||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
@@ -59,18 +60,37 @@
|
|||||||
: and then encoded with base64 encoding.
|
: and then encoded with base64 encoding.
|
||||||
-->
|
-->
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
<xsd:complexType>
|
<xsd:complexType>
|
||||||
<xsd:choice maxOccurs="unbounded">
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
<xsd:element name="data">
|
<xsd:element name="data">
|
||||||
<xsd:complexType>
|
<xsd:complexType>
|
||||||
<xsd:sequence>
|
<xsd:sequence>
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="resheader">
|
<xsd:element name="resheader">
|
||||||
@@ -89,378 +109,34 @@
|
|||||||
<value>text/microsoft-resx</value>
|
<value>text/microsoft-resx</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="version">
|
<resheader name="version">
|
||||||
<value>1.3</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="btnStart.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="timerPoll.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="btnStart.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="btnStart.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="btnStop.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="btnStop.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="btnStop.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadsInPool.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadsInPool.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadsInPool.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label5.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label5.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label5.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinIdleTimeout.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinIdleTimeout.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinIdleTimeout.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMaxThreads.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMaxThreads.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMaxThreads.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMinThreads.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMinThreads.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinMinThreads.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinInterval.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinInterval.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinInterval.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadInUse.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadInUse.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblThreadInUse.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label7.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label7.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label7.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="timerPoll.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="timerPoll.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="timerPoll.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="pcActiveThreads.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinConsumingTime.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinConsumingTime.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="spinConsumingTime.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label6.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label6.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label6.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWaitingCallbacks.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWaitingCallbacks.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWaitingCallbacks.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label9.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label9.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label9.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label8.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label8.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label8.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label10.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="label10.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="label10.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsGenerated.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsGenerated.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsGenerated.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsCompleted.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsCompleted.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="lblWorkItemsCompleted.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>8, 8</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>8, 8</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>8, 8</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageThreadsInPool.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageThreadsInPool.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageThreadsInPool.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>8, 8</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="groupBox4.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageHistorySTP.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageHistorySTP.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="usageHistorySTP.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcActiveThreads.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcActiveThreads.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcActiveThreads.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>112, 17</value>
|
<value>112, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="pcInUseThreads.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="pcInUseThreads.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcInUseThreads.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcInUseThreads.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>245, 17</value>
|
<value>245, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="pcQueuedWorkItems.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="pcQueuedWorkItems.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcQueuedWorkItems.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcQueuedWorkItems.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>377, 17</value>
|
<value>377, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="pcCompletedWorkItems.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="pcCompletedWorkItems.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcCompletedWorkItems.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="pcCompletedWorkItems.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>533, 17</value>
|
<value>533, 17</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>False</value>
|
<value>87</value>
|
||||||
</data>
|
</metadata>
|
||||||
<data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<value>(Default)</value>
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
</data>
|
|
||||||
<data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>False</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>8, 8</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>59</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>True</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.Name">
|
|
||||||
<value>Form1</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
|
||||||
<value>Private</value>
|
|
||||||
</data>
|
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>
|
<value>
|
||||||
AAABAAIAICAQAAAAAADoAgAAJgAAABAQEAAAAAAAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC
|
AAABAAIAICAQAAAAAADoAgAAJgAAABAQEAAAAAAAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC
|
||||||
AAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/
|
AAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/
|
||||||
|
|||||||
@@ -71,6 +71,16 @@
|
|||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>
|
||||||
|
</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System">
|
<Reference Include="System">
|
||||||
<Name>System</Name>
|
<Name>System</Name>
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:2.0.50727.42
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace UsageControl.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UsageControl.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
namespace UsageControl
|
||||||
|
{
|
||||||
|
partial class QueueUsageControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.timer1 = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// timer1
|
||||||
|
//
|
||||||
|
this.timer1.Enabled = true;
|
||||||
|
this.timer1.Interval = 500;
|
||||||
|
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
|
||||||
|
//
|
||||||
|
// QueueUsageControl
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.BackColor = System.Drawing.Color.Transparent;
|
||||||
|
this.Name = "QueueUsageControl";
|
||||||
|
this.Size = new System.Drawing.Size(167, 247);
|
||||||
|
this.Resize += new System.EventHandler(this.QueueUsageControl_Resize);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Timer timer1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,342 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Data;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
|
||||||
|
namespace UsageControl
|
||||||
|
{
|
||||||
|
public partial class QueueUsageControl : UserControl
|
||||||
|
{
|
||||||
|
private List<QueueUsageEntry> _queuedItems;
|
||||||
|
private int _maxItemsVisible = 0;
|
||||||
|
private int _lastVisibleItemIndex = 0;
|
||||||
|
private int _itemHeight = 0;
|
||||||
|
private Dictionary<Color, Bitmap> _imagesCache = new Dictionary<Color, Bitmap>();
|
||||||
|
private GraphicsPath _pathBorder;
|
||||||
|
private RectangleF [] _slots;
|
||||||
|
private bool _invalidate = true;
|
||||||
|
|
||||||
|
public QueueUsageControl()
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("QueueUsageControl");
|
||||||
|
|
||||||
|
EnableDoubleBuffering();
|
||||||
|
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
ControlRezised();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap GenerateItemImage(string text, Color color, int width, int height, Font font)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("GenerateItemImage");
|
||||||
|
|
||||||
|
Bitmap itemImage = null;
|
||||||
|
Rectangle rc = new Rectangle(0, 0, width, height);
|
||||||
|
itemImage = new Bitmap(rc.Width, rc.Height);
|
||||||
|
|
||||||
|
/// Create button
|
||||||
|
rc.Inflate(-3, -3);
|
||||||
|
GraphicsPath path1 = GetPath(rc, 10);
|
||||||
|
rc.Inflate(0, 6);
|
||||||
|
LinearGradientBrush br1 = new LinearGradientBrush(rc, color, Color.White, LinearGradientMode.Vertical);
|
||||||
|
rc.Inflate(0, -6);
|
||||||
|
|
||||||
|
/// Create shadow
|
||||||
|
Rectangle rc2 = rc;
|
||||||
|
rc2.Offset(8, 8);
|
||||||
|
GraphicsPath path2 = GetPath(rc2, 20);
|
||||||
|
PathGradientBrush br2 = new PathGradientBrush(path2);
|
||||||
|
br2.CenterColor = ControlPaint.DarkDark(Color.Silver);
|
||||||
|
br2.SurroundColors = new Color[] { Color.White };
|
||||||
|
|
||||||
|
/// Create bubble
|
||||||
|
Rectangle rc3 = rc;
|
||||||
|
rc3.Inflate(-15, -rc.Height / 3);
|
||||||
|
rc3.Y = rc3.Y - 2;
|
||||||
|
//rc3.Height = rc3.Height;
|
||||||
|
GraphicsPath path3 = GetPath(rc3, rc3.Height);
|
||||||
|
LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
|
||||||
|
|
||||||
|
itemImage = new Bitmap(width - 2, height);
|
||||||
|
Graphics g = Graphics.FromImage(itemImage);
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.FillPath(br2, path2);
|
||||||
|
g.FillPath(br1, path1);
|
||||||
|
g.FillPath(br3, path3);
|
||||||
|
|
||||||
|
//SizeF size = g.MeasureString(text, font);
|
||||||
|
//int fontHeight = (int)size.Height + 5;
|
||||||
|
|
||||||
|
//g.DrawString(
|
||||||
|
// text,
|
||||||
|
// font,
|
||||||
|
// Brushes.Black,
|
||||||
|
// new RectangleF((rc.Width - size.Width) / 2, 2, width, fontHeight));
|
||||||
|
|
||||||
|
return itemImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap GetItemsImage(Color color)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("GetItemsImage");
|
||||||
|
|
||||||
|
Bitmap itemImage = null;
|
||||||
|
|
||||||
|
if (!_imagesCache.ContainsKey(color))
|
||||||
|
{
|
||||||
|
Rectangle rc = new Rectangle(0, 0, this.Width, _itemHeight);
|
||||||
|
itemImage = new Bitmap(rc.Width, rc.Height);
|
||||||
|
|
||||||
|
/// Create button
|
||||||
|
rc.Inflate(-3, -3);
|
||||||
|
GraphicsPath path1 = GetPath(rc, 10);
|
||||||
|
rc.Inflate(0, 6);
|
||||||
|
LinearGradientBrush br1 = new LinearGradientBrush(rc, color, Color.White, LinearGradientMode.Vertical);
|
||||||
|
rc.Inflate(0, -6);
|
||||||
|
|
||||||
|
/// Create shadow
|
||||||
|
Rectangle rc2 = rc;
|
||||||
|
rc2.Offset(8, 8);
|
||||||
|
GraphicsPath path2 = GetPath(rc2, 20);
|
||||||
|
PathGradientBrush br2 = new PathGradientBrush(path2);
|
||||||
|
br2.CenterColor = ControlPaint.DarkDark(Color.Silver);
|
||||||
|
br2.SurroundColors = new Color[] { Color.White };
|
||||||
|
|
||||||
|
/// Create bubble
|
||||||
|
Rectangle rc3 = rc;
|
||||||
|
rc3.Inflate(-15, -rc.Height / 3);
|
||||||
|
rc3.Y = rc3.Y - 2;
|
||||||
|
//rc3.Height = rc3.Height;
|
||||||
|
GraphicsPath path3 = GetPath(rc3, rc3.Height);
|
||||||
|
LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
|
||||||
|
|
||||||
|
itemImage = new Bitmap(this.Width - 2, _itemHeight);
|
||||||
|
Graphics g = Graphics.FromImage(itemImage);
|
||||||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
|
g.FillPath(br2, path2);
|
||||||
|
g.FillPath(br1, path1);
|
||||||
|
g.FillPath(br3, path3);
|
||||||
|
|
||||||
|
_imagesCache[color] = itemImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemImage = _imagesCache[color];
|
||||||
|
|
||||||
|
return itemImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnableDoubleBuffering()
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("EnableDoubleBuffering");
|
||||||
|
|
||||||
|
// Set the value of the double-buffering style bits to true.
|
||||||
|
this.SetStyle(ControlStyles.DoubleBuffer |
|
||||||
|
ControlStyles.UserPaint |
|
||||||
|
ControlStyles.AllPaintingInWmPaint |
|
||||||
|
ControlStyles.SupportsTransparentBackColor,
|
||||||
|
true);
|
||||||
|
this.UpdateStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("Reset");
|
||||||
|
_queuedItems = new List<QueueUsageEntry>();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public void Queue(string text, Color color, bool blink)
|
||||||
|
//{
|
||||||
|
// //Debug.WriteLine("Queue");
|
||||||
|
// _queuedItems.Add(new QueueUsageEntry(text, color, blink));
|
||||||
|
// //this.Invalidate();
|
||||||
|
//}
|
||||||
|
|
||||||
|
public void SetQueue(List<QueueUsageEntry> list)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("SetQueue");
|
||||||
|
bool invalidate = false;
|
||||||
|
|
||||||
|
if (_queuedItems.Count != list.Count)
|
||||||
|
{
|
||||||
|
invalidate = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int counter = Math.Min(list.Count, _maxItemsVisible);
|
||||||
|
for (int i = 0; i < counter; i++)
|
||||||
|
{
|
||||||
|
if (_queuedItems[i] != list[i])
|
||||||
|
{
|
||||||
|
invalidate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalidate)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("_invalidate = true");
|
||||||
|
_queuedItems = list;
|
||||||
|
_invalidate = invalidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
//_queuedItems = list;
|
||||||
|
//_queuedItems.Clear();
|
||||||
|
//foreach (QueueUsageEntry entry in list)
|
||||||
|
//{
|
||||||
|
// _queuedItems.Add(entry);
|
||||||
|
//}
|
||||||
|
//_invalidate = true;
|
||||||
|
//this.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("OnPaint");
|
||||||
|
|
||||||
|
Bitmap bitmap = new Bitmap(Width, Height);
|
||||||
|
Graphics g = Graphics.FromImage(bitmap);
|
||||||
|
|
||||||
|
g.FillPath(Brushes.White, _pathBorder);
|
||||||
|
|
||||||
|
int counter = Math.Min(_maxItemsVisible, _queuedItems.Count);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (QueueUsageEntry entry in _queuedItems)
|
||||||
|
{
|
||||||
|
if (i > counter)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//int top = 0;
|
||||||
|
//int bottom = 0;
|
||||||
|
//if (topdown)
|
||||||
|
//{
|
||||||
|
// bottom = 1;
|
||||||
|
// top = bottom;
|
||||||
|
// top += i * _itemHeight;
|
||||||
|
// bottom += (i + 1) * _itemHeight;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// bottom = this.Height - 1;
|
||||||
|
// top = bottom;
|
||||||
|
// bottom -= i * _itemHeight;
|
||||||
|
// top -= (i + 1) * _itemHeight;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//g.DrawLine(Pens.Black, 0, top, this.Width, top);
|
||||||
|
|
||||||
|
|
||||||
|
string text = (entry.IsExecuting ? ">" : "") + entry.Text;
|
||||||
|
if (i == _lastVisibleItemIndex)
|
||||||
|
{
|
||||||
|
text = "(" + (_queuedItems.Count - _maxItemsVisible) + ")...";
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeF size = g.MeasureString(entry.Text, this.Font);
|
||||||
|
//Debug.WriteLine(size.Width);
|
||||||
|
|
||||||
|
Bitmap itemImage = GetItemsImage(entry.Color);
|
||||||
|
|
||||||
|
RectangleF slot = _slots[i];
|
||||||
|
|
||||||
|
//g.DrawImage(itemImage, -1, top);
|
||||||
|
g.DrawImage(itemImage, -1, slot.Top-2);
|
||||||
|
|
||||||
|
//g.DrawString(text, this.Font, Brushes.Black, new RectangleF((this.Width - size.Width) / 2, top + 2, this.Width, bottom));
|
||||||
|
g.DrawString(text, this.Font, Brushes.Black, slot);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
g.DrawPath(Pens.Black, _pathBorder);
|
||||||
|
//g.DrawRectangle(Pens.Black, border);
|
||||||
|
|
||||||
|
e.Graphics.DrawImage(bitmap, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GraphicsPath GetPath(Rectangle rc, int r)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("GetPath");
|
||||||
|
int x = rc.X, y = rc.Y, w = rc.Width, h = rc.Height;
|
||||||
|
GraphicsPath path = new GraphicsPath();
|
||||||
|
path.AddArc(x, y, r, r, 180, 90); //Upper left corner
|
||||||
|
path.AddArc(x + w - r, y, r, r, 270, 90); //Upper right corner
|
||||||
|
path.AddArc(x + w - r, y + h - r, r, r, 0, 90); //Lower right corner
|
||||||
|
path.AddArc(x, y + h - r, r, r, 90, 90); //Lower left corner
|
||||||
|
path.CloseFigure();
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ControlRezised()
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("ControlRezised");
|
||||||
|
Graphics g = Graphics.FromHwnd(this.Handle);
|
||||||
|
SizeF size = g.MeasureString("X", this.Font);
|
||||||
|
g.Dispose();
|
||||||
|
_itemHeight = (int)size.Height + 5;
|
||||||
|
_maxItemsVisible = this.Height / _itemHeight - 1;
|
||||||
|
_lastVisibleItemIndex = _maxItemsVisible;
|
||||||
|
_imagesCache = new Dictionary<Color, Bitmap>();
|
||||||
|
|
||||||
|
Rectangle border = new Rectangle(0, 0, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
|
||||||
|
_pathBorder = GetPath(border, 20);
|
||||||
|
|
||||||
|
PrepareSlots();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareSlots()
|
||||||
|
{
|
||||||
|
bool topdown = true;
|
||||||
|
_slots = new RectangleF[_maxItemsVisible+5];
|
||||||
|
for (int i = 0; i < _slots.Length; i++)
|
||||||
|
{
|
||||||
|
int top = 0;
|
||||||
|
int bottom = 0;
|
||||||
|
if (topdown)
|
||||||
|
{
|
||||||
|
bottom = 1;
|
||||||
|
top = bottom;
|
||||||
|
top += i * _itemHeight;
|
||||||
|
bottom += (i + 1) * _itemHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bottom = this.Height - 1;
|
||||||
|
top = bottom;
|
||||||
|
bottom -= i * _itemHeight;
|
||||||
|
top -= (i + 1) * _itemHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
_slots[i] = new RectangleF((this.Width - 55) / 2, top + 2, this.Width, bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void QueueUsageControl_Resize(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine("QueueUsageControl_Resize");
|
||||||
|
ControlRezised();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timer1_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_invalidate)
|
||||||
|
{
|
||||||
|
_invalidate = false;
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace UsageControl
|
||||||
|
{
|
||||||
|
public partial class QueueUsageControl
|
||||||
|
{
|
||||||
|
public class QueueUsageEntry
|
||||||
|
{
|
||||||
|
private string _text;
|
||||||
|
private Color _color;
|
||||||
|
private bool _isExecuting;
|
||||||
|
|
||||||
|
public QueueUsageEntry(
|
||||||
|
string text,
|
||||||
|
Color color) : this (text, color, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueueUsageEntry(
|
||||||
|
string text,
|
||||||
|
Color color,
|
||||||
|
bool blink)
|
||||||
|
{
|
||||||
|
_text = text;
|
||||||
|
_color = color;
|
||||||
|
_isExecuting = blink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color
|
||||||
|
{
|
||||||
|
get { return _color; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get { return _text; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsExecuting
|
||||||
|
{
|
||||||
|
get { return _isExecuting; }
|
||||||
|
set { _isExecuting = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -73,6 +73,16 @@
|
|||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<BaseAddress>285212672</BaseAddress>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>
|
||||||
|
</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System">
|
<Reference Include="System">
|
||||||
<Name>System</Name>
|
<Name>System</Name>
|
||||||
@@ -94,12 +104,35 @@
|
|||||||
<Compile Include="AssemblyInfo.cs">
|
<Compile Include="AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="QueueUsageControl.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="QueueUsageControl.Designer.cs">
|
||||||
|
<DependentUpon>QueueUsageControl.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="QueueUsageEntry.cs">
|
||||||
|
<SubType>UserControl</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="UsageControl.cs">
|
<Compile Include="UsageControl.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="UsageHistoryControl.cs">
|
<Compile Include="UsageHistoryControl.cs">
|
||||||
<SubType>UserControl</SubType>
|
<SubType>UserControl</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="QueueUsageControl.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<DependentUpon>QueueUsageControl.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="UsageControl.resx">
|
<EmbeddedResource Include="UsageControl.resx">
|
||||||
<DependentUpon>UsageControl.cs</DependentUpon>
|
<DependentUpon>UsageControl.cs</DependentUpon>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
|||||||
Generated
+1269
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,372 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using UsageControl;
|
||||||
|
using Amib.Threading;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupDemo
|
||||||
|
{
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
private bool _running = false;
|
||||||
|
private bool _paused = false;
|
||||||
|
private bool _advancedMode = false;
|
||||||
|
private int _workItemsGenerated;
|
||||||
|
Hashtable _workingStates = Hashtable.Synchronized(new Hashtable());
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
private IWorkItemsGroup _wig1;
|
||||||
|
private IWorkItemsGroup _wig2;
|
||||||
|
private IWorkItemsGroup _wig3;
|
||||||
|
|
||||||
|
private int[] _lastIndex = new int[4];
|
||||||
|
|
||||||
|
private static readonly Color _stpColor = Color.Gray;
|
||||||
|
private static readonly Color _wig1Color = Color.Red;
|
||||||
|
private static readonly Color _wig2Color = Color.Green;
|
||||||
|
private static readonly Color _wig3Color = Color.Blue;
|
||||||
|
|
||||||
|
|
||||||
|
private class WigEntry
|
||||||
|
{
|
||||||
|
public IWorkItemsGroup _wig;
|
||||||
|
public QueueUsageControl _queueUsageControl;
|
||||||
|
public Label _isIdle;
|
||||||
|
|
||||||
|
public WigEntry(
|
||||||
|
IWorkItemsGroup wig,
|
||||||
|
QueueUsageControl queueUsageControl,
|
||||||
|
Label isIdle)
|
||||||
|
{
|
||||||
|
_wig = wig;
|
||||||
|
_queueUsageControl = queueUsageControl;
|
||||||
|
_isIdle = isIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WigEntry[] _wigEntries = null;
|
||||||
|
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
InitSTP();
|
||||||
|
|
||||||
|
UpdateControls(false);
|
||||||
|
UpdateModeControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitSTP()
|
||||||
|
{
|
||||||
|
STPStartInfo stpStartInfo = new STPStartInfo();
|
||||||
|
stpStartInfo.StartSuspended = true;
|
||||||
|
stpStartInfo.MaxWorkerThreads = (int)spinCon6.Value;
|
||||||
|
stpStartInfo.IdleTimeout = 5000;
|
||||||
|
stpStartInfo.PerformanceCounterInstanceName = "SmartThreadPoolDemo";
|
||||||
|
|
||||||
|
_stp = new SmartThreadPool(stpStartInfo);
|
||||||
|
_wig1 = _stp.CreateWorkItemsGroup((int)spinCon1.Value);
|
||||||
|
_wig2 = _stp.CreateWorkItemsGroup((int)spinCon2.Value);
|
||||||
|
_wig3 = _stp.CreateWorkItemsGroup((int)spinCon3.Value);
|
||||||
|
|
||||||
|
spinCon1.Tag = _wig1;
|
||||||
|
spinCon2.Tag = _wig2;
|
||||||
|
spinCon3.Tag = _wig3;
|
||||||
|
spinCon6.Tag = _stp;
|
||||||
|
|
||||||
|
comboWIPriority1.SelectedIndex = 1;
|
||||||
|
comboWIPriority2.SelectedIndex = 1;
|
||||||
|
comboWIPriority3.SelectedIndex = 1;
|
||||||
|
comboWIPriority6.SelectedIndex = 1;
|
||||||
|
|
||||||
|
_wigEntries = new WigEntry[]
|
||||||
|
{
|
||||||
|
new WigEntry(_wig1, queueUsageControl1, lblStatus1),
|
||||||
|
new WigEntry(_wig2, queueUsageControl2, lblStatus2),
|
||||||
|
new WigEntry(_wig3, queueUsageControl3, lblStatus3),
|
||||||
|
};
|
||||||
|
for (int i = 0; i < _lastIndex.Length; i++)
|
||||||
|
{
|
||||||
|
_lastIndex[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnStart_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_running = !_running;
|
||||||
|
btnStart.Text = _running ? "Stop STP" : "Start STP";
|
||||||
|
|
||||||
|
if (_running)
|
||||||
|
{
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
_workItemsGenerated = 0;
|
||||||
|
UpdateControls(true);
|
||||||
|
_stp.Start();
|
||||||
|
_wig1.Start();
|
||||||
|
_wig2.Start();
|
||||||
|
_wig3.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Shutdown()
|
||||||
|
{
|
||||||
|
_stp.Shutdown(false, 2000);
|
||||||
|
InitSTP();
|
||||||
|
UpdateControls(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateControls(bool start)
|
||||||
|
{
|
||||||
|
timerPoll.Enabled = start;
|
||||||
|
|
||||||
|
lblThreadInUse.Text = "0";
|
||||||
|
lblThreadsInPool.Text = "0";
|
||||||
|
lblWaitingCallbacks.Text = "0";
|
||||||
|
usageThreadsInPool.Value1 = 0;
|
||||||
|
usageThreadsInPool.Value2 = 0;
|
||||||
|
lblWorkItemsCompleted.Text = "0";
|
||||||
|
lblWorkItemsGenerated.Text = "0";
|
||||||
|
usageHistorySTP.Reset();
|
||||||
|
usageHistorySTP.Maximum = usageThreadsInPool.Maximum;
|
||||||
|
|
||||||
|
spinIdleTimeout.Enabled = !start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DoNothing(object state)
|
||||||
|
{
|
||||||
|
WorkItemState workItemState = (WorkItemState)state;
|
||||||
|
_workingStates.Add(workItemState.QueueUsageEntry, workItemState.QueueUsageEntry);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (SmartThreadPool.IsWorkItemCanceled)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Thread.Sleep(workItemState.SleepDuration);
|
||||||
|
} while (_paused);
|
||||||
|
_workingStates.Remove(workItemState.QueueUsageEntry);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void timer1_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
foreach (WigEntry wigEntry in _wigEntries)
|
||||||
|
{
|
||||||
|
UpdateQueueUsageControl(
|
||||||
|
wigEntry._wig,
|
||||||
|
wigEntry._queueUsageControl,
|
||||||
|
wigEntry._isIdle);
|
||||||
|
|
||||||
|
}
|
||||||
|
UpdateWorkingSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateWorkingSet()
|
||||||
|
{
|
||||||
|
lblStatus6.Text = _stp.IsIdle ? "Idle" : "Working";
|
||||||
|
|
||||||
|
object [] statesWorking = null;
|
||||||
|
lock (_workingStates.SyncRoot)
|
||||||
|
{
|
||||||
|
statesWorking = new object[_workingStates.Count];
|
||||||
|
_workingStates.Keys.CopyTo(statesWorking, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
object[] statesSTP = _stp.GetStates();
|
||||||
|
|
||||||
|
List<QueueUsageControl.QueueUsageEntry> list = new List<QueueUsageControl.QueueUsageEntry>();
|
||||||
|
|
||||||
|
foreach (QueueUsageControl.QueueUsageEntry entry in statesWorking)
|
||||||
|
{
|
||||||
|
if (null != entry)
|
||||||
|
{
|
||||||
|
entry.IsExecuting = true;
|
||||||
|
list.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (WorkItemState state in statesSTP)
|
||||||
|
{
|
||||||
|
if (null != state)
|
||||||
|
{
|
||||||
|
list.Add(state.QueueUsageEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queueUsageControl6.SetQueue(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateQueueUsageControl(
|
||||||
|
IWorkItemsGroup wig,
|
||||||
|
QueueUsageControl queueUsageControl,
|
||||||
|
Label label)
|
||||||
|
{
|
||||||
|
label.Text = wig.IsIdle ? "Idle" : "Working";
|
||||||
|
object[] states = wig.GetStates();
|
||||||
|
|
||||||
|
List<QueueUsageControl.QueueUsageEntry> list = new List<QueueUsageControl.QueueUsageEntry>();
|
||||||
|
|
||||||
|
foreach (WorkItemState state in states)
|
||||||
|
{
|
||||||
|
if (null != state)
|
||||||
|
{
|
||||||
|
list.Add(state.QueueUsageEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queueUsageControl.SetQueue(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnPause_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_paused = !_paused;
|
||||||
|
btnPause.Text = _paused ? "Resume STP" : "Pause STP";
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Test functions
|
||||||
|
private void btnState1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
List<QueueUsageControl.QueueUsageEntry> list = new List<QueueUsageControl.QueueUsageEntry>();
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#A", Color.Yellow));
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#B", Color.Green));
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#C", Color.Black));
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#D", Color.HotPink));
|
||||||
|
queueUsageControl1.SetQueue(list);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnState2_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
List<QueueUsageControl.QueueUsageEntry> list = new List<QueueUsageControl.QueueUsageEntry>();
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#1", Color.Cyan));
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#2", Color.Magenta));
|
||||||
|
list.Add(new QueueUsageControl.QueueUsageEntry("#3", Color.Red));
|
||||||
|
queueUsageControl1.SetQueue(list);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region WorkItemState class
|
||||||
|
|
||||||
|
private class WorkItemState
|
||||||
|
{
|
||||||
|
public readonly QueueUsageControl.QueueUsageEntry QueueUsageEntry;
|
||||||
|
public readonly int SleepDuration;
|
||||||
|
|
||||||
|
public WorkItemState(
|
||||||
|
QueueUsageControl.QueueUsageEntry queueUsageEntry,
|
||||||
|
int sleepDuration)
|
||||||
|
{
|
||||||
|
QueueUsageEntry = queueUsageEntry;
|
||||||
|
SleepDuration = sleepDuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void EnqueueWorkItems(ref int startIndex, int count, string text, Color color, WorkItemPriority priority, IWorkItemsGroup wig, int sleepDuration)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i, ++startIndex)
|
||||||
|
{
|
||||||
|
wig.QueueWorkItem(
|
||||||
|
DoNothing,
|
||||||
|
new WorkItemState(new QueueUsageControl.QueueUsageEntry(string.Format("{0}{1} ({2})", text, startIndex, priority.ToString().Substring(0,2 )), color), sleepDuration),
|
||||||
|
priority);
|
||||||
|
}
|
||||||
|
_workItemsGenerated += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_wig1.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel2_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_wig2.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel3_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_wig3.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCancel6_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_stp.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spinCon_ValueChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
NumericUpDown spin = sender as NumericUpDown;
|
||||||
|
IWorkItemsGroup wig = spin.Tag as IWorkItemsGroup;
|
||||||
|
wig.Concurrency = (int)spin.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timer2_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
EnqueueWorkItems(ref _lastIndex[0], Convert.ToInt32(spinProduction1.Value), "#", _wig1Color, (WorkItemPriority)(2 * comboWIPriority1.SelectedIndex), _wig1, Convert.ToInt32(spinDuration1.Value));
|
||||||
|
EnqueueWorkItems(ref _lastIndex[1], Convert.ToInt32(spinProduction2.Value), "#", _wig2Color, (WorkItemPriority)(2 * comboWIPriority2.SelectedIndex), _wig2, Convert.ToInt32(spinDuration2.Value));
|
||||||
|
EnqueueWorkItems(ref _lastIndex[2], Convert.ToInt32(spinProduction3.Value), "#", _wig3Color, (WorkItemPriority)(2 * comboWIPriority3.SelectedIndex), _wig3, Convert.ToInt32(spinDuration3.Value));
|
||||||
|
EnqueueWorkItems(ref _lastIndex[3], Convert.ToInt32(spinProduction6.Value), "#", _stpColor, (WorkItemPriority)(2 * comboWIPriority6.SelectedIndex), _stp, Convert.ToInt32(spinDuration6.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnMode_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_advancedMode = !_advancedMode;
|
||||||
|
UpdateModeControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateModeControls()
|
||||||
|
{
|
||||||
|
btnMode.Text = _advancedMode ? "Basic <<" : "Advanced >>";
|
||||||
|
panelWIGsCtrls.Visible = _advancedMode;
|
||||||
|
groupWIGQueues.Visible = _advancedMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerPoll_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
SmartThreadPool stp = _stp;
|
||||||
|
if (null == stp)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int threadsInUse = (int)pcInUseThreads.NextValue();
|
||||||
|
int threadsInPool = (int)pcActiveThreads.NextValue();
|
||||||
|
|
||||||
|
lblThreadInUse.Text = threadsInUse.ToString();
|
||||||
|
lblThreadsInPool.Text = threadsInPool.ToString();
|
||||||
|
lblWaitingCallbacks.Text = pcQueuedWorkItems.NextValue().ToString(); //stp.WaitingCallbacks.ToString();
|
||||||
|
usageThreadsInPool.Value1 = threadsInUse;
|
||||||
|
usageThreadsInPool.Value2 = threadsInPool;
|
||||||
|
lblWorkItemsCompleted.Text = pcCompletedWorkItems.NextValue().ToString();
|
||||||
|
lblWorkItemsGenerated.Text = _workItemsGenerated.ToString();
|
||||||
|
usageHistorySTP.AddValues(threadsInUse, threadsInPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Form1_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
label5.Image = QueueUsageControl.GenerateItemImage("", _wig1Color, 72, label5.Height, label5.Font); ;
|
||||||
|
label4.Image = QueueUsageControl.GenerateItemImage("", _wig2Color, 72, label5.Height, label5.Font); ;
|
||||||
|
label3.Image = QueueUsageControl.GenerateItemImage("", _wig3Color, 72, label5.Height, label5.Font); ;
|
||||||
|
label8.Image = QueueUsageControl.GenerateItemImage("", _stpColor, 72, label5.Height, label5.Font); ;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>94, 4</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 7</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>94, 4</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="timer2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>186, 4</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="pcActiveThreads.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 54</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="pcInUseThreads.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>150, 54</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="pcQueuedWorkItems.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>282, 54</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="pcCompletedWorkItems.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>438, 54</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="timerPoll.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>609, 54</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
|
<value>25</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace WorkItemsGroupDemo
|
||||||
|
{
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new Form1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("WindowsApplication1")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("WindowsApplication1")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2006")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("68872ba4-6524-406b-9c96-cf8ca3f4c729")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:2.0.50727.832
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace WorkItemsGroupDemo.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WorkItemsGroupDemo.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:2.0.50727.832
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace WorkItemsGroupDemo.Properties {
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default {
|
||||||
|
get {
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.50727</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{DC005A64-FAE9-4CFA-ADC8-F1D1FE7FE6CD}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>WorkItemsGroupDemo</RootNamespace>
|
||||||
|
<AssemblyName>WorkItemsGroupDemo</AssemblyName>
|
||||||
|
<StartupObject>WorkItemsGroupDemo.Program</StartupObject>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseCE|AnyCPU' ">
|
||||||
|
<OutputPath>bin\ReleaseCE\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Deployment" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Form1.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Form1.Designer.cs">
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<EmbeddedResource Include="Form1.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<DependentUpon>Form1.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
</Compile>
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SmartThreadPool\SmartThreadPool.csproj">
|
||||||
|
<Project>{8684FC56-A679-4E2E-8F96-E172FB062EB6}</Project>
|
||||||
|
<Name>SmartThreadPool</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\UsageControl\UsageControl.csproj">
|
||||||
|
<Project>{C11A4561-CCB5-4C96-8DF2-B804031D89D8}</Project>
|
||||||
|
<Name>UsageControl</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user