ConcurrencyCheck.cs

Check and Store Concurrency Usage

using System;
using System.Diagnostics;
using System.Threading;
public class ConcurrencyCheck
{
    public volatile ConcurrencyInfo concurrencyInfo = new ConcurrencyInfo();
    private         int             ProcessorCount => Environment.ProcessorCount;
    public bool OverrideAutoConcurrency
    {
        get;
        set;
    }
    public bool QuickCheck
    {
        get;
        set;
    } = false;
    public bool UsingConcurrency
    {
        get;
        private set;
    }
    public bool CheckState()
    {
        if (OverrideAutoConcurrency)
            return false;
        if (QuickCheck && concurrencyInfo.Calls > ProcessorCount && concurrencyInfo.LockState == 0)
            return false;
        if (concurrencyInfo.StatusThreadId != Thread.CurrentThread.ManagedThreadId)
        {
            concurrencyInfo.StatusThreadId = Thread.CurrentThread.ManagedThreadId;
            concurrencyInfo.Add(concurrencyInfo.StatusThreadId);
        }
        if (concurrencyInfo.LockState == 1)
            return true;
        if (concurrencyInfo.BeginningThreadId == 0 && concurrencyInfo.LockState == 0 && Thread.CurrentThread.ManagedThreadId != 0)
            concurrencyInfo.BeginningThreadId = Thread.CurrentThread.ManagedThreadId;
        if (concurrencyInfo.LockState == 0)
            if (concurrencyInfo.BeginningThreadId != Thread.CurrentThread.ManagedThreadId)
            {
                concurrencyInfo.LockState = 1;
                UsingConcurrency          = true;
                return true;
            }
        concurrencyInfo.Calls++;
        return false;
    }
    [DebuggerDisplay("UniqueThreadIds = {ActiveThreads}")]
    public class ConcurrencyInfo
    {
        public volatile int     ActiveThreads=1;
        public volatile int     BeginningThreadId;
        public volatile int     Calls;
        public volatile ulong[] ContextSwitches = new ulong[32768];
        public volatile int     LockState;
        public volatile int     StatusThreadId;
        public volatile int[]   UniqueThreadIds = new int[32768];
        public void Add(int value)
        {
            if (UniqueThreadIds[value] != value)
            {
                UniqueThreadIds[value] = value;
                ActiveThreads++;
                return;
            }
            ContextSwitches[value]++;
        }
    }
}

Reporter.cs

Thread Reporter used with IProgress

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
[ComVisible(true)]
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public class Reporter
{
    public readonly ConcurrentDictionary<string, object> GValues  = new ConcurrentDictionary<string, object>();
    public          List<string>                         ErrorLog = new List<string>();
    public Reporter()
    {
    }
    public Reporter(string DescriptorID)
    {
        LoadDescriptorFile(DescriptorID);
    }
    public string ProgramDir
    {
        get
        {
            var dir = Services.GetEnvironmentEx("Local AppData") + "\\" + Application.ProductName + "\\";
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            return dir;
        }
    }
    public void SaveDescriptorFile(string DescriptorID)
    {
        var anx = ProgramDir + DescriptorID + "_file.bin";
        var iel = GValues.ToArray();
        using (var wrt = new Writer(anx))
        {
            foreach (var i in iel)
            {
                wrt.WriteString(i.Key);
                wrt.WriteBytes(i.Value.GetBytesObjectSerial());
            }
        }
    }
    public void LoadDescriptorFile(string DescriptorID)
    {
        var anx = ProgramDir + DescriptorID + "_file.bin";
        if (!File.Exists(anx))
            throw new Exception($"file {anx} does not exist.");
        GValues.Clear();
        using (var rdr = new Reader(anx))
        {
            var key   = rdr.ReadString();
            var value = rdr.ReadBytes();
            GValues.TryAdd(key, value);
        }
    }
    public bool DescriptorFileExists(string DescriptorID)
    {
        var anx = ProgramDir + DescriptorID + "_file.bin";
        return File.Exists(anx);
    }
    public bool CheckDescriptorExists(string DescriptorID)
    {
        return GValues.ContainsKey(DescriptorID);
    }
    public void BuildDescriptorList(List<string> lst)
    {
        foreach (var i in lst)
            Set(i, default);
    }
    public void Set(string DescriptorID, object value)
    {
        if (!GValues.ContainsKey(DescriptorID))
            GValues.TryAdd(DescriptorID, value);
        else GValues[DescriptorID] = value;
    }
    public bool GetBool(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToBoolean(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return false;
    }
    public char GetChar(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToChar(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return ' ';
    }
    public sbyte GetSByte(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToSByte(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public byte GetByte(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToByte(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public short GetShort(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToInt16(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public ushort GetUShort(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToUInt16(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public int GetInt(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToInt32(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public uint GetUInt(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToUInt32(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public long GetLong(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToInt64(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public ulong GetULong(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToUInt64(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public float GetFloat(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToSingle(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public double GetDouble(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToDouble(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public decimal GetDecimal(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToDecimal(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return 0;
    }
    public string GetString(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToString(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return " ";
    }
    public DateTime GetDateTime(string DescriptorID)
    {
        if (GValues.TryGetValue(DescriptorID, out var ov))
            try
            {
                return Convert.ToDateTime(ov);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null) ErrorLog.Add(ex.InnerException.ToString());
            }
        return default;
    }
}