public bool TakeMessage(string queueName, CancellationToken token, out MessageEnvelope envelope)
		{
			envelope = null;

			while (!token.IsCancellationRequested)
			{
				var queue = this.GetQueue(queueName);
				var result = this.TryGetMessage(queue, out envelope);
				switch (result)
				{
					case GetMessageResult.Success:
						this._retryCount = 0;
						return true;
					case GetMessageResult.Empty:
					case GetMessageResult.Retry:
						this._retryCount += 1;
						break;
					case GetMessageResult.Exception:
						return false;
					default:
						throw new ArgumentOutOfRangeException();
				}

				if (this._retryCount > RetryCount)
					break;

				var waiting = this._waiter(this._retryCount);
				token.WaitHandle.WaitOne(waiting);
			}

			return false;
		}
		public GetMessageResult TryGetMessage(CloudQueue queue, out MessageEnvelope envelope)
		{
			CloudQueueMessage message = null;
			envelope = null;
			try
			{
				message = queue.GetMessage(new TimeSpan(0, 2, 0)); // 2 min timeout
			}
			catch (Exception ex)
			{
				this.Observer.Notify(new FailedToReadMessage(ex, queue.Name));
				return GetMessageResult.Exception;
			}

			if (message == null)
			{
				return GetMessageResult.Empty;
			}

			if (message.DequeueCount > RetryCount)
			{
				this.Observer.Notify(new RetrievedPoisonMessage(queue.Name, message.Id));
				return GetMessageResult.Retry;
			}

			try
			{
				envelope = SerializationUtility.Deserialize<MessageEnvelope>(this.Serializer, message.AsBytes);
				//try download from blob
				if (!envelope.MessageReference.IsLoaded)
				{
					if (envelope.MessageReference.StorageContainer != this.CloudBlob.Uri.ToString())
					{
						throw new InvalidOperationException("Wrong container used!");
					}
					var blob = this.CloudBlob.GetBlobReferenceFromServer(envelope.MessageReference.StorageReference);
					var messageType = Type.GetType(envelope.MessageReference.MessageTypeName);
					var stream = new MemoryStream();
					blob.DownloadToStream(stream);
					envelope.MessageReference.Message = SerializationUtility.Deserialize(messageType, this.Serializer, stream.ToArray()) as IMessage;
				}
				envelope.TransportMessage = message;
			}
			catch (StorageException ex)
			{
				this.Observer.Notify(new FailedToAccessStorage(ex, queue.Name, message.Id));
				return GetMessageResult.Retry;
			}
			catch (Exception ex)
			{
				this.Observer.Notify(new FailedToDeserializeMessage(ex, queue.Name, message.Id));
				return GetMessageResult.Exception;
			}

			return GetMessageResult.Success;
		}
		public void DeleteMessage(MessageEnvelope envelope)
		{
			if (envelope == null)
			{
				throw new ArgumentNullException("envelope");
			}
			var queue = this.GetQueue(envelope.QueueName);
			queue.DeleteMessage((CloudQueueMessage)envelope.TransportMessage);
			if (envelope.MessageReference.StorageReference != null)
			{
				var blob = this.CloudBlob.GetBlobReferenceFromServer(envelope.MessageReference.StorageReference);
				blob.DeleteIfExists();
			}
			this.Observer.Notify(new MessageAcked(queue.Name, envelope.EnvelopeId));
		}
		private CloudQueueMessage PrepareCloudMessage(MessageEnvelope envelope)
		{
			CloudQueueMessage retVal = null;
			var buffer = SerializationUtility.Serialize(this.Serializer, envelope);
			if (buffer.Length > CloudQueueLimit && envelope.MessageReference.Message != null)
			{
				var referenceId = DateTimeOffset.UtcNow.ToString(DateFormatInBlobName) + "-" + envelope.EnvelopeId;
				var messageBuffer = SerializationUtility.Serialize(this.Serializer, envelope.MessageReference.Message);
				this.CloudBlob.GetBlobReferenceFromServer(referenceId).UploadFromStream(new MemoryStream(messageBuffer));

				var msgTypeName = envelope.MessageReference.Message.GetType().AssemblyQualifiedName;
				envelope.MessageReference = new MessageReference(this.CloudBlob.Uri.ToString(), referenceId, msgTypeName);
				buffer = SerializationUtility.Serialize(this.Serializer, envelope);
			}
			retVal = new CloudQueueMessage(buffer);
			return retVal;
		}
 public void PutMessage(MessageEnvelope envelope)
 {
     MemoryQueueClient.Queue.Enqueue(envelope);
 }
		public void PutMessage(MessageEnvelope envelope)
		{
			var message = this.PrepareCloudMessage(envelope);
			var queue = this.GetQueue(envelope.QueueName);
			queue.AddMessage(message);
		}
		public bool TakeMessage(string queueName, CancellationToken token, out MessageEnvelope envelope)
		{
			envelope = MemoryQueueClient.Queue.Dequeue(10);
			return envelope != null;
		}
		public void DeleteMessage(MessageEnvelope envelope)
		{
			//MemoryQueueClient.Queue..Enqueue(envelope);
		}