private Action mapAction(MainForm formHandle, Actionable action, Dictionary<string, int> serverMap, CancellationToken token)
        {
            return new Action(() =>
            {
                var gridTasks = new List<Task>();
                foreach (string serverName in serverMap.Keys)
                {
                    int x = serverMap[serverName];
                    gridTasks.Add(Task.Factory.StartNew(() =>
                        formHandle.setServerData(x, action.Name, "\u231B", getColorForActionStatus(ActionStatus.Queued))));
                }
                Task.WaitAll(gridTasks.ToArray());

                try
                {

                    int atOnce;
                    if (action.MaxRunning == -1)
                        atOnce = serverMap.Keys.Count;
                    else
                        atOnce = action.MaxRunning;

                    int segments = serverMap.Keys.Count / atOnce;
                    if (segments * atOnce < serverMap.Keys.Count) segments++;
                    var keys = serverMap.Keys.ToArray();

                    for (int i = 0; i < segments; i++)
                    {
                        var tasks = new List<Task>();
                        for (int j = i * atOnce; j < (i * atOnce) + atOnce; j++)
                        {
                            if (j < serverMap.Keys.Count)
                            {
                                string serverName = keys[j];
                                int x = serverMap[serverName];
                                string name = serverName;
                                tasks.Add(Task.Factory.StartNew(() =>
                                {
                                    try
                                    {
                                        formHandle.setServerData(x, action.Name, "In progress...", getColorForActionStatus(ActionStatus.Pending));
                                        Task<ActionResult> t = Task.Factory.StartNew<ActionResult>(wrapFunc(action.WorkFunc, name), token);
                                        t.Wait(token);
                                        string result;
                                        if (action.Post != null)
                                        {
                                            result = action.Post.Invoke(t.Result.Message);
                                        }
                                        else
                                        {
                                            result = t.Result.Message;
                                        }
                                        formHandle.setServerData(x, action.Name, result, getColorForActionStatus(t.Result.Status));
                                    }
                                    catch (Exception e)
                                    {
                                        formHandle.setServerData(x, action.Name, "Operation cancelled.", getColorForActionStatus(ActionStatus.Unknown));
                                    }
                                }, token));
                            }
                        }
                        try
                        {
                            Task.WaitAll(tasks.ToArray(), token);
                        }
                        catch (OperationCanceledException opex)
                        {
                            throw opex;
                        }

                    }

                    formHandle.addToActionLog("Completed: " + action.Name);
                    action.Running = false;
                    formHandle.refreshActionListControls();
                    if (action.Repeat) this.Run(action.Name, formHandle.getEnabledServers());
                }
                catch (OperationCanceledException opex)
                {
                    var indices = serverMap.Values.ToList();
                    var stillPending = formHandle.getPendingIndices(indices, action.Name);
                    foreach (int i in stillPending)
                    {
                        formHandle.setServerData(i, action.Name, "Operation cancelled.", getColorForActionStatus(ActionStatus.Unknown));
                    }
                    formHandle.addToActionLog("Cancelled: " + action.Name);
                    action.Running = false;
                    formHandle.refreshActionListControls();
                }

                lock (action.runLock)
                {
                    action.Running = false;
                }
            });
        }
 public ActionRunner(MainForm form)
 {
     actions = new Dictionary<string, Actionable>();
     _form = form;
 }