private List <UpdateTask> RunTasks(UpdateTask[] tasks, bool multithreadedTaskRunning, int maxParallelTasks) { List <UpdateTask> failedTasks = new List <UpdateTask>(); List <string> filesToDelete = new List <string>(); using (ManualResetEvent resetEvent = new ManualResetEvent(false)) { int tasksToRun = tasks.Length; int tasksActive = 0; for (int i = 0; i < tasks.Length; i++) { UpdateTask curTask = tasks[i]; if (multithreadedTaskRunning) { if (tasksActive == maxParallelTasks) { Thread.Sleep(10); i--; continue; } bool queued = false; while (!queued) { queued = ThreadPool.QueueUserWorkItem( new WaitCallback( task => { try { int tasksDone = tasks.Length - tasksToRun; percentageDone = Convert.ToInt32(((double)(tasksDone - failedTasks.Count) / (double)tasks.Length) * 100d); TriggerProgressEvent(percentageDone, curTask.ToString()); ((UpdateTask)task).Run(); } catch (Exception) { failedTasks.Add(curTask); } finally { if (Interlocked.Decrement(ref tasksToRun) == 0) { resetEvent.Set(); } Interlocked.Decrement(ref tasksActive); filesToDelete.AddRange(((UpdateTask)curTask).filesToDeleteOnExit); } } ), curTask ); if (!queued) { Thread.Sleep(10); } else { Interlocked.Increment(ref tasksActive); } } } else { percentageDone = Convert.ToInt32(((double)(i - failedTasks.Count) / (double)tasks.Length) * 100d); TriggerProgressEvent(percentageDone, curTask.ToString()); try { curTask.Run(); } catch (Exception ex) { failedTasks.Add(curTask); } finally { filesToDelete.AddRange(((UpdateTask)curTask).filesToDeleteOnExit); resetEvent.Set(); } } } resetEvent.WaitOne(); foreach (string curFile in filesToDelete) { try { File.Delete(curFile); }catch (Exception) { Console.WriteLine("Failed to delete " + curFile); } } } return(failedTasks); }