/// <summary>
		/// Adds a task to the queue specified in the task itself and sends a message to
		/// the associated channel, notifying any listeners.
		/// </summary>
		/// <param name="t"></param>
		public void Enqueue(TaskMessage t)
		{
			if (string.IsNullOrEmpty(t.Queue))
				throw new NoQueueSpecifiedException(	
					"TaskMessage.Queue is empty or null. Cannot append task to queue.");

			var queue = new QueueName(t.Queue);
			
			_taskMessageClient.Lists[queue.NameWhenPending].Add(t);
			SendMessage(QueueSystemMessages.TaskAvailable.ToString(), queue);

			_log.Info("New task in [" + queue.NameWhenPending + "]");
			_log.DebugFormat("Task Parameters: {0}", t.Parameters);
		}
		/// <summary>
		/// Obtains the first available task from the specified queue, and changes the client's
		/// state into TaskReserved. In that state, no new tasks can be reserved until the 
		/// task's outcome is evident.
		/// </summary>
		/// <param name="queue"></param>
		/// <returns></returns>
		public TaskMessage Reserve(QueueName queue)
		{
			if (_state == RedisQueueState.TaskReserved)
				throw new TaskAlreadyReservedException("Cannot reserve multiple tasks at once.");

			if (string.IsNullOrEmpty(queue.ToString()))
				throw new NoQueueSpecifiedException(
					"Parameter <queue> is empty or null. Cannot retrieve task for no queue.");

			if (_taskMessageClient.Lists[queue.NameWhenPending].Count == 0)
				throw new QueueIsEmptyException("No tasks available in specified queue.");

			CurrentTask = _taskMessageClient.Lists[queue.NameWhenPending].RemoveStart();
			_state = RedisQueueState.TaskReserved;

			_log.Info("Reserved task from [" + queue.NameWhenPending + "]");
			_log.DebugFormat("Task Parameters: {0}", CurrentTask.Parameters);

			return CurrentTask;
		}
		/// <summary>
		/// Removes a task with a specific task identifier.
		/// </summary>
		/// <param name="task"></param>
		public void RemoveTask(TaskMessage task)
		{
			var queueName = new QueueName(task.Queue);
			removeTask(queueName.NameWhenPending, task);
			removeTask(queueName.NameWhenFailed, task);
			removeTask(queueName.NameWhenSucceeded, task);
		}
		private void removeTask(string queue, TaskMessage task)
		{
			var results = new List<TaskMessage>();
			TaskMessage t;
			while((t = _taskMessageClient.Lists[queue].RemoveStart()) != null)
			{
				if (t.Equals(task)) continue;
				results.Add(t);
			}

			if (results.Count > 0)
				_taskMessageClient.Lists[queue].AddRange(results);
		}
		public bool Equals(TaskMessage other)
		{
			if (ReferenceEquals(null, other)) return false;
			if (ReferenceEquals(this, other)) return true;
			return Equals(other._queue, _queue) && other.Identifier.Equals(Identifier) && Equals(other.Parameters, Parameters);
		}