public static TOutput RunLockedFunc <TInput1, TInput2, TOutput>(
            this SemaphoreSlim semaphore,
            TInput1 input1,
            TInput2 input2,
            Func <TInput1, TInput2, TOutput> action)
        {
            semaphore.Wait();

            try
            {
                return(action(input1, input2));
            }
            finally
            {
                semaphore.Release();
            }
        }
        public static async Task <TOutput> RunLockedFuncAsync <TInput, TOutput>(
            this SemaphoreSlim semaphore,
            Func <TInput, TOutput> func,
            TInput input,
            CancellationToken cancellationToken)
        {
            await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                return(func(input));
            }
            finally
            {
                semaphore.Release();
            }
        }