private void WaitActionLockPendingCompletations(ref SocketRequest request, ref IController controller, ref string actionName)
        {
            if (!ActionLocker.ActionHasLock(controller, actionName))
            {
                return;
            }
            SingleThreaded actionLock = method.GetCustomAttribute <SingleThreaded>();

            if (actionLock == null)
            {
                return;
            }

            for (int i = 0; i < actionLock.WaitingAttempts; i++)
            {
                if (ActionLocker.ActionHasLock(controller, actionName))
                {
                    if ((i + 1) >= actionLock.WaitingAttempts)
                    {
                        throw new LockedActionException("The action does not allow simultaneous access and the maximum number of waiting attempts has been exceeded. Try to access the resource again later.");
                    }

                    Thread.Sleep(actionLock.WaitingInterval);
                }
                else
                {
                    return;
                }
            }
        }
        public override object DoInBackGround(int p)
        {
            SocketRequest request = null;

            try
            {
                request = GetRequestSocket();
                if (request == null)
                {
                    return(null);
                }

                if (HasRequestErros(ref request))
                {
                    return(null);
                }

                controller = request.Controller;
                method     = controller.GetType().GetMethod(request.Action);

                ValidateActionMethod();

                controllerName = controller.GetType().Name;
                actionName     = method.Name;

                WaitActionLockPendingCompletations(ref request,
                                                   ref controller, ref actionName);

                if (method.GetCustomAttribute <SingleThreaded>() != null)
                {
                    ActionLocker.AddLock(controller, actionName);
                }

                ResolveActionParameters(ref request);
                if (!ResolveInterceptors(ref request))
                {
                    return(null);
                }

                ParameterInfo[] methodParameters     = method.GetParameters();
                object[]        parameterValues      = new object[methodParameters.Length];
                int             methodParameterCount = methodParameters
                                                       .Where(pr => request.Parameters.Any(rp => rp.Name.Equals(pr.Name)))
                                                       .Count();

                int parameterIndex = 0;
                int valueIndex     = 0;
                foreach (RequestParameter rp in request.Parameters)
                {
                    ParameterInfo parameterInfo = methodParameters.FirstOrDefault(mp => mp.Name.Equals(rp.Name));
                    if (parameterInfo == null)
                    {
                        parameterIndex += 1;
                        continue;
                    }

                    parameterValues[valueIndex] = request.Parameters[parameterIndex].Value;
                    parameterIndex += 1;
                    valueIndex     += 1;
                }

                ActionResult result = null;
                Stopwatch    w      = new Stopwatch();
                w.Start();

                if (method.ReturnType == null)
                {
                    //void action
                    method.Invoke(controller, parameterValues);
                    result = ActionResult.Json(new OperationResult(null, 600, ""));
                }
                else if (method.ReturnType == typeof(ActionResult)) //ActionResult action
                {
                    result = (ActionResult)method.Invoke(controller, parameterValues);
                }
                else
                {
                    //user-defined object Action
                    object returnObj = method.Invoke(controller, parameterValues);
                    result = ActionResult.Json(new OperationResult(returnObj, 600, ""));
                }

                w.Stop();

                if (telemetry != null)
                {
                    telemetry.Collect(new ActionExecutionTime(controllerName, actionName, w.ElapsedMilliseconds));
                }

                logger.WriteLog($"Request completed: {controllerName}/{actionName}; ~{w.ElapsedMilliseconds}ms");

                if (w.ElapsedMilliseconds > 10000)
                {
                    ServerAlertManager.CreateAlert(new ServerAlert(request.Controller.GetType().Name, request.Action,
                                                                   $"The action it is taking considerable time to execute ({w.ElapsedMilliseconds} ms). Review your code to improve performance.'"));
                }

                ActionLocker.ReleaseLock(controller, method.Name);
                request.ProcessResponse(result, clientSocket, requestBody.InTo);
                return(result);
            }
            catch (LockedActionException lockedEx)
            {
                ProcessErrorResponse(lockedEx, ref request);
                return(null);
            }
            catch (Exception ex)
            {
                if (method != null &&
                    controller != null)
                {
                    ActionLocker.ReleaseLock(controller, actionName);
                }

                ProcessErrorResponse(ex, ref request);
                return(null);
            }
        }