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]++;
        }
    }
}

MonitorActionFunc.cs

Use to Lock Local Functions with Concurrency

using System;
using System.Threading;
public class MonitorActionFunc : ConcurrencyCheck
{
    public void Lock(object localObject, Action action)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                action();
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        else
        {
            action();
        }
    }
    public TResult Lock<TResult>(object localObject, Func<TResult> func)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                return func();
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        return func();
    }
    public (TResult1, TResult2) Lock<TResult1, TResult2>(object localObject, Func<(TResult1, TResult2)> func)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                return func();
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        return func();
    }
    public (TResult1, TResult2) Lock<TArg, TResult1, TResult2>(object localObject, Func<TArg, (TResult1, TResult2)> func, TArg arg)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                return func(arg);
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        return func(arg);
    }
    public TResult Lock<TArg, TResult>(object localObject, Func<TArg, TResult> func, TArg arg)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                return func(arg);
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        return func(arg);
    }
    public void Lock<TArg>(object localObject, Action<TArg> action, TArg arg)
    {
        if (CheckState())
        {
            var lockTaken = false;
            try
            {
                Monitor.Enter(localObject, ref lockTaken);
                action(arg);
            }
            finally
            {
                if (lockTaken)
                    Monitor.Exit(localObject);
            }
        }
        else
        {
            action(arg);
        }
    }
}