Catalog/imagecatalog.backup/XYThreadPool.cs
2024-10-14 18:54:30 +02:00

273 lines
No EOL
8.2 KiB
C#

using System;
using System.Collections;
using System.Threading;
namespace ImageCatalog
{
public delegate void ThreadErrorHandlerDelegate(ThreadPoolWorkItem oWorkItem, Exception oError);
public class ThreadPoolWorkItem
{
public bool m_bStoreOutput = false;
public string m_sName = "";
public Delegate m_pMethod = null;
public object[] m_pInput = null;
public object m_oOutput = null;
public Exception m_oException = null;
public ThreadPoolWorkItem()
{
}
public ThreadPoolWorkItem(string sName, Delegate pMethod, object[] pInput, bool bStoreOutput)
{
m_sName = sName;
m_pMethod = pMethod;
m_pInput = pInput;
m_bStoreOutput = bStoreOutput;
}
}
public class XYThreadPool
{
public XYThreadPool()
{
m_delegateThreadErrorHandler = new ThreadErrorHandlerDelegate(OnThreadError);
}
private Hashtable m_htThreads = new Hashtable(256);
private int m_nMinThreadCount = 5;
private int m_nMaxThreadCount = 10;
private int m_nShutdownPause = 200;
private int m_nServerPause = 25;
private bool m_bContinue = false;
private Exception m_oException = null;
private Queue m_qInput = new Queue(1024);
private Queue m_qOutput = new Queue(1024);
private Delegate m_delegateThreadErrorHandler;
private void ThreadProc()
{
while (m_bContinue)
{
object obj = null;
Monitor.Enter(this);
if (m_qInput.Count > 0)
obj = m_qInput.Dequeue();
Monitor.Exit(this);
if (obj is null)
{
bool bQuit = false;
Monitor.Enter(this);
if (m_htThreads.Count > m_nMinThreadCount)
{
m_htThreads.Remove(Thread.CurrentThread.Name);
bQuit = true;
}
Monitor.Exit(this);
if (bQuit)
return;
Thread.Sleep(10 * m_nServerPause);
}
else
{
ThreadPoolWorkItem oWorkItem = (ThreadPoolWorkItem)obj;
// oWorkItem.m_oOutput = oWorkItem.m_pMethod.DynamicInvoke(oWorkItem.m_pInput)
try
{
oWorkItem.m_oOutput = oWorkItem.m_pMethod.DynamicInvoke(oWorkItem.m_pInput);
}
catch (Exception oBug)
{
if (m_delegateThreadErrorHandler is object)
{
try
{
var pInput = new object[] { oWorkItem, oBug };
m_delegateThreadErrorHandler.DynamicInvoke(pInput);
}
catch
{
}
}
}
if (oWorkItem.m_bStoreOutput)
{
Monitor.Enter(m_qOutput);
m_qOutput.Enqueue(oWorkItem);
Monitor.Exit(m_qOutput);
}
Thread.Sleep(m_nServerPause);
}
}
}
private void OnThreadError(ThreadPoolWorkItem oWorkItem, Exception oError)
{
if (oWorkItem is null)
{
m_oException = oError;
}
else
{
oWorkItem.m_oException = oError;
}
}
public void SetThreadErrorHandler(ThreadErrorHandlerDelegate pMethod)
{
Monitor.Enter(this);
m_delegateThreadErrorHandler = pMethod;
Monitor.Exit(this);
}
public void SetServerPause(int nMilliseconds)
{
Monitor.Enter(this);
if (nMilliseconds > 9 & nMilliseconds < 101)
m_nServerPause = nMilliseconds;
Monitor.Exit(this);
}
public void SetShutdownPause(int nMilliseconds)
{
Monitor.Enter(this);
m_nShutdownPause = nMilliseconds;
Monitor.Exit(this);
}
public Exception GetException()
{
return m_oException;
}
public void InsertWorkItem(ThreadPoolWorkItem oWorkItem)
{
try
{
Monitor.Enter(this);
m_qInput.Enqueue(oWorkItem);
if (m_bContinue && m_qInput.Count > m_htThreads.Count && m_htThreads.Count < m_nMaxThreadCount)
{
var th = new Thread(ThreadProc);
th.Name = Guid.NewGuid().ToString();
m_htThreads.Add(th.Name, th);
th.Start();
}
}
catch (Exception oBug)
{
m_oException = oBug;
}
finally
{
Monitor.Exit(this);
}
}
public void InsertWorkItem(string sName, Delegate pMethod, object[] pArgs, bool bStoreOutput)
{
InsertWorkItem(new ThreadPoolWorkItem(sName, pMethod, pArgs, bStoreOutput));
}
public ThreadPoolWorkItem ExtractWorkItem()
{
object oWorkItem = null;
Monitor.Enter(m_qOutput);
if (m_qOutput.Count > 0)
oWorkItem = m_qOutput.Dequeue();
Monitor.Exit(m_qOutput);
if (oWorkItem is null)
return null;
return (ThreadPoolWorkItem)oWorkItem;
}
public bool StartThreadPool(int nMinThreadCount = 5, int nMaxThreadCount = 10)
{
try
{
Monitor.Enter(this);
if (m_bContinue == false)
{
m_bContinue = true;
if (nMinThreadCount > 0)
{
m_nMinThreadCount = nMinThreadCount;
}
if (nMaxThreadCount > m_nMinThreadCount)
{
m_nMaxThreadCount = nMaxThreadCount;
}
else
{
m_nMaxThreadCount = 2 * m_nMinThreadCount;
}
int i;
var loopTo = m_nMinThreadCount;
for (i = 1; i <= loopTo; i++)
{
var th = new Thread(ThreadProc);
th.Name = Guid.NewGuid().ToString();
m_htThreads.Add(th.Name, th);
th.Start();
}
}
return true;
}
catch (Exception oBug)
{
m_bContinue = false;
m_oException = oBug;
return false;
}
finally
{
Monitor.Exit(this);
}
}
public void StopThreadPool()
{
Monitor.Enter(this);
m_bContinue = false;
Thread.Sleep(Math.Max(200, m_nShutdownPause));
if (m_nShutdownPause > 0)
{
var dict = m_htThreads.GetEnumerator();
while (dict.MoveNext())
{
Thread th = (Thread)dict.Value;
if (th.IsAlive)
{
try
{
th.Abort();
}
catch
{
}
}
}
}
m_htThreads.Clear();
m_qInput.Clear();
// m_qOutput.Clear()
Monitor.Exit(this);
}
public int GetThreadCount()
{
Monitor.Enter(this);
int nCount = m_htThreads.Count;
Monitor.Exit(this);
return nCount;
}
}
}