public function run(DateTimeInterface $now = NULL)
	{
		if ($now === NULL) {
			$now = new DateTime();
		}
		if ($this->maxExecutionTime !== NULL) {
			set_time_limit($this->maxExecutionTime);
		}

		foreach ($this->tasks as $task) {
			try {
				$name = $task->getName();
				if ($task->shouldBeRun($now)) {
					if ($this->criticalSection->enter($name)) {
						$this->onTaskBegin($this, $task);
						$task($now);
						$this->onTaskFinished($this, $task);
						$this->criticalSection->leave($name);
					}
				}
			} catch (Exception $e) {
				$this->onTaskError($this, $e, $task);
				$name = $task->getName();
				if ($this->criticalSection->isEntered($name)) {
					$this->criticalSection->leave($name);
				}
				if ($e instanceof RuntimeException) {
					throw $e; // Throw exception if it is Cronner Runtime exception
				} elseif ($this->skipFailedTask === FALSE) {
					throw $e; // Throw exception if failed task should not be skipped
				}
			}
		}
	}