public void Initialize(EntityInfo entity, Func <IncomingMessageDetails, ReceiveContext, Task> callback, Func <Exception, Task> errorCallback, Func <ErrorContext, Task <ErrorHandleResult> > processingFailureCallback, int maximumConcurrency)
        {
            receiveMode = settings.Get <ReceiveMode>(WellKnownConfigurationKeys.Connectivity.MessageReceivers.ReceiveMode);

            incomingCallback               = callback;
            this.errorCallback             = errorCallback ?? EmptyErrorCallback;
            this.processingFailureCallback = processingFailureCallback;
            this.entity = entity;

            fullPath = entity.Path;
            if (entity.Type == EntityType.Subscription)
            {
                var topic = entity.RelationShips.First(r => r.Type == EntityRelationShipType.Subscription);
                fullPath = SubscriptionClient.FormatSubscriptionPath(topic.Target.Path, entity.Path);
            }

            var transportTransactionMode = settings.HasExplicitValue <TransportTransactionMode>() ? settings.Get <TransportTransactionMode>() : settings.SupportedTransactionMode();

            wrapInScope            = transportTransactionMode == TransportTransactionMode.SendsAtomicWithReceive;
            completionCanBeBatched = !wrapInScope;
            autoRenewTimeout       = settings.Get <TimeSpan>(WellKnownConfigurationKeys.Connectivity.MessageReceivers.AutoRenewTimeout);
            numberOfClients        = settings.Get <int>(WellKnownConfigurationKeys.Connectivity.NumberOfClientsPerEntity);
            var concurrency = maximumConcurrency / (double)numberOfClients;

            maxConcurrentCalls = concurrency > 1 ? (int)Math.Round(concurrency, MidpointRounding.AwayFromZero) : 1;
            if (Math.Abs(maxConcurrentCalls - concurrency) > 0)
            {
                logger.InfoFormat("The maximum concurrency on message receiver instance for '{0}' has been adjusted to '{1}', because the total maximum concurrency '{2}' wasn't divisable by the number of clients '{3}'", fullPath, maxConcurrentCalls, maximumConcurrency, numberOfClients);
            }

            internalReceivers = new IMessageReceiver[numberOfClients];
            onMessageOptions  = new OnMessageOptions[numberOfClients];
            completion        = new MultiProducerConcurrentCompletion <Guid>(1000, TimeSpan.FromSeconds(1), 6, numberOfClients);
        }
        public void Initialize(EntityInfoInternal entity, Func <IncomingMessageDetailsInternal, ReceiveContextInternal, Task> callback, Func <Exception, Task> errorCallback, Action <Exception> criticalError, Func <ErrorContext, Task <ErrorHandleResult> > processingFailureCallback, int maximumConcurrency)
        {
            incomingCallback               = callback;
            this.criticalError             = criticalError;
            this.errorCallback             = errorCallback ?? EmptyErrorCallback;
            this.processingFailureCallback = processingFailureCallback;
            this.entity = entity;

            fullPath = entity.Path;
            if (entity.Type == EntityType.Subscription)
            {
                var topic = entity.RelationShips.First(r => r.Type == EntityRelationShipTypeInternal.Subscription);
                fullPath = SubscriptionClient.FormatSubscriptionPath(topic.Target.Path, entity.Path);
            }

            wrapInScope = settings.TransportTransactionMode == TransportTransactionMode.SendsAtomicWithReceive;
            // batching will be applied for transaction modes other than SendsAtomicWithReceive
            completionCanBeBatched = !wrapInScope;

            var numberOfClients = settings.NumberOfClients;
            var concurrency     = maximumConcurrency / (double)numberOfClients;

            maxConcurrentCalls = concurrency > 1 ? (int)Math.Round(concurrency, MidpointRounding.AwayFromZero) : 1;
            if (Math.Abs(maxConcurrentCalls - concurrency) > 0)
            {
                logger.InfoFormat("The maximum concurrency on message receiver instance for '{0}' has been adjusted to '{1}', because the total maximum concurrency '{2}' wasn't divisable by the number of clients '{3}'", fullPath, maxConcurrentCalls, maximumConcurrency, numberOfClients);
            }

            internalReceivers = new IMessageReceiverInternal[numberOfClients];
            onMessageOptions  = new OnMessageOptions[numberOfClients];

            // when we don't batch we don't need the completion infrastructure
            completion = completionCanBeBatched ? new MultiProducerConcurrentCompletion <Guid>(1000, TimeSpan.FromSeconds(1), 6, numberOfClients) : null;
        }
        protected override void ProcessRecord()
        {
            string[]    chunks = Context.ChunkPath(this.SessionState.Path.CurrentLocation);
            ReceiveMode mode   = this.PeekLock.IsPresent ? ReceiveMode.PeekLock : ReceiveMode.ReceiveAndDelete;

            string path = this.From;

            if (chunks[0] == "Topics")
            {
                path = SubscriptionClient.FormatSubscriptionPath(chunks[1], this.From);
            }

            BrokeredMessage message  = null;
            MessageReceiver receiver = this.Factory.CreateMessageReceiver(path, mode);

            try
            {
                message = receiver.Receive(TimeSpan.FromSeconds(10));
            }
            finally
            {
                // Setting a timer to close the receiver after a minute. User has to complete the message in this time window
                new Timer(CloseReceiver, (object)receiver, TimeSpan.FromMinutes(1), TimeSpan.FromMilliseconds(-1));
            }

            if (message != null)
            {
                message.Properties.Add("Body", message.GetBody <string>());
            }

            this.WriteObject(message);
        }
Example #4
0
        public Task <ITriggerBinding> TryCreateAsync(TriggerBindingProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            ParameterInfo parameter = context.Parameter;
            ServiceBusTriggerAttribute attribute = parameter.GetCustomAttribute <ServiceBusTriggerAttribute>(inherit: false);

            if (attribute == null)
            {
                return(Task.FromResult <ITriggerBinding>(null));
            }

            string queueName        = null;
            string topicName        = null;
            string subscriptionName = null;
            string entityPath       = null;

            if (attribute.QueueName != null)
            {
                queueName  = Resolve(attribute.QueueName);
                entityPath = queueName;
            }
            else
            {
                topicName        = Resolve(attribute.TopicName);
                subscriptionName = Resolve(attribute.SubscriptionName);
                entityPath       = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
            }

            ITriggerDataArgumentBinding <BrokeredMessage> argumentBinding = InnerProvider.TryCreate(parameter);

            if (argumentBinding == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Can't bind ServiceBusTrigger to type '{0}'.", parameter.ParameterType));
            }

            string            connectionName = ServiceBusAccount.GetAccountOverrideOrNull(context.Parameter);
            ServiceBusAccount account        = new ServiceBusAccount
            {
                MessagingFactory = _config.MessagingProvider.CreateMessagingFactory(entityPath, connectionName),
                NamespaceManager = _config.MessagingProvider.CreateNamespaceManager(connectionName)
            };

            ITriggerBinding binding;

            if (queueName != null)
            {
                binding = new ServiceBusTriggerBinding(parameter.Name, parameter.ParameterType, argumentBinding, account, queueName, attribute.Access, _config);
            }
            else
            {
                binding = new ServiceBusTriggerBinding(parameter.Name, argumentBinding, account, topicName, subscriptionName, attribute.Access, _config);
            }

            return(Task.FromResult <ITriggerBinding>(binding));
        }
 public ServiceBusTriggerBinding(string parameterName, Type parameterType, ITriggerDataArgumentBinding <BrokeredMessage> argumentBinding, ServiceBusAccount account,
                                 AccessRights accessRights, ServiceBusConfiguration config, string topicName, string subscriptionName)
     : this(parameterName, parameterType, argumentBinding, account, accessRights, config)
 {
     _topicName        = topicName;
     _subscriptionName = subscriptionName;
     _entityPath       = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
 }
Example #6
0
 public ServiceBusTriggerBinding(string parameterName,
                                 ITriggerDataArgumentBinding <BrokeredMessage> argumentBinding, ServiceBusAccount account, string topicName,
                                 string subscriptionName)
 {
     _parameterName    = parameterName;
     _argumentBinding  = argumentBinding;
     _account          = account;
     _namespaceName    = ServiceBusClient.GetNamespaceName(account);
     _topicName        = topicName;
     _subscriptionName = subscriptionName;
     _entityPath       = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
 }
        private void CreateSubscription(ServiceBusConnectionContext connectionContext, int topicIndex)
        {
            lock (connectionContext.SubscriptionsLock)
            {
                if (connectionContext.IsDisposed)
                {
                    return;
                }

                string topicName = connectionContext.TopicNames[topicIndex];

                // Create a random subscription
                string subscriptionName = Guid.NewGuid().ToString();

                try
                {
                    var subscriptionDescription = new SubscriptionDescription(topicName, subscriptionName);

                    // This cleans up the subscription while if it's been idle for more than the timeout.
                    subscriptionDescription.AutoDeleteOnIdle = _idleSubscriptionTimeout;

                    _namespaceManager.CreateSubscription(subscriptionDescription);

                    _trace.TraceInformation("Creation of a new subscription {0} for topic {1} in the service bus completed successfully.", subscriptionName, topicName);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                    // The entity already exists
                    _trace.TraceInformation("Creation of a new subscription {0} for topic {1} threw an MessagingEntityAlreadyExistsException.", subscriptionName, topicName);
                }

                // Create a receiver to get messages
                string          subscriptionEntityPath = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
                MessageReceiver receiver = _factory.CreateMessageReceiver(subscriptionEntityPath, ReceiveMode.ReceiveAndDelete);

                _trace.TraceInformation("Creation of a message receive for subscription entity path {0} in the service bus completed successfully.", subscriptionEntityPath);

                connectionContext.SetSubscriptionContext(new SubscriptionContext(topicName, subscriptionName, receiver), topicIndex);

                var receiverContext = new ReceiverContext(topicIndex, receiver, connectionContext);

                var task = Task.Run(() => ProcessMessages(receiverContext));
                _processMessagesTasks.GetOrAdd(task, false);
                task.ContinueWith(t =>
                {
                    bool value;
                    _processMessagesTasks.TryRemove(task, out value);
                });

                // Open the stream
                connectionContext.OpenStream(topicIndex);
            }
        }
Example #8
0
        public async Task <IListener> CreateAsync(IFunctionExecutor executor, CancellationToken cancellationToken)
        {
            // Must create all messaging entities before creating message receivers and calling OnMessage.
            // Otherwise, some function could start to execute and try to output messages to entities that don't yet
            // exist.
            await _namespaceManager.CreateTopicIfNotExistsAsync(_topicName, cancellationToken);

            await _namespaceManager.CreateSubscriptionIfNotExistsAsync(_topicName, _subscriptionName,
                                                                       cancellationToken);

            string entityPath = SubscriptionClient.FormatSubscriptionPath(_topicName, _subscriptionName);

            ITriggerExecutor <BrokeredMessage> triggerExecutor = new ServiceBusTriggerExecutor(_instanceFactory,
                                                                                               executor);

            return(new ServiceBusListener(_messagingFactory, entityPath, triggerExecutor));
        }
Example #9
0
        internal static async Task <ISubscription> ForAsync(AzureServiceBusConfiguration configuration, Type eventType, string subscriptionName)
        {
            var topicPath = Conventions.TopicPath(eventType);

            var namespaceManager   = NamespaceManager.CreateFromConnectionString(configuration.ConnectionString);
            var subscriptionExists = await namespaceManager.SubscriptionExistsAsync(topicPath, subscriptionName);

            if (!subscriptionExists)
            {
                await namespaceManager.CreateSubscriptionAsync(topicPath, subscriptionName);
            }

            var messagingFactory = MessagingFactory.CreateFromConnectionString(configuration.ConnectionString);

            var subscriptionPath = SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName);

            var receiver = await messagingFactory.CreateMessageReceiverAsync(subscriptionPath, ReceiveMode.PeekLock);

            return(new Subscription(receiver, eventType));
        }
Example #10
0
        public override void Listen(Channel channel, Action <object>[] routeactions, string channelpath)
        {
            var client = SubscriptionClient.CreateFromConnectionString(channel.ToConnectionString, channel.ToPath, channel.ToSubscription);

            var path = SubscriptionClient.FormatSubscriptionPath(channel.ToPath, channel.ToSubscription);

            var receiver = client.MessagingFactory.CreateMessageReceiver(path);

            var options = CreateOptions();

            Action <BrokeredMessage> routeaction = message =>
            {
                foreach (var action in routeactions)
                {
                    var clone = message.Clone();
                    action(clone);
                }
            };

            receiver.OnMessage(bm => OnMessage(channelpath, bm.MessageId, () => routeaction(bm), () => client.Complete(bm.LockToken)), options);

            channel.Shutdown = () => { receiver.Close(); client.Close(); };
        }
 void GetEntityData(bool deadLetterQueueData, out long messageCount, out string entityPath)
 {
     if (deadLetterQueueData)
     {
         if (queueDescription != null)
         {
             var queueDescription2 = serviceBusHelper.GetQueue(queueDescription.Path);
             messageCount = queueDescription2.MessageCountDetails.DeadLetterMessageCount;
             entityPath   = QueueClient.FormatDeadLetterPath(queueDescription.Path);
         }
         else
         {
             var subscriptionDescription = serviceBusHelper.GetSubscription(subscriptionWrapper.TopicDescription.Path,
                                                                            subscriptionWrapper.SubscriptionDescription.Name);
             messageCount = subscriptionDescription.MessageCountDetails.DeadLetterMessageCount;
             entityPath   = SubscriptionClient.FormatDeadLetterPath(subscriptionWrapper.SubscriptionDescription.TopicPath,
                                                                    subscriptionWrapper.SubscriptionDescription.Name);
         }
     }
     else
     {
         if (queueDescription != null)
         {
             var queueDescription2 = serviceBusHelper.GetQueue(queueDescription.Path);
             messageCount = queueDescription2.MessageCountDetails.ActiveMessageCount;
             entityPath   = queueDescription.Path;
         }
         else
         {
             var subscriptionDescription = serviceBusHelper.GetSubscription(subscriptionWrapper.TopicDescription.Path,
                                                                            subscriptionWrapper.SubscriptionDescription.Name);
             messageCount = subscriptionDescription.MessageCountDetails.ActiveMessageCount;
             entityPath   = SubscriptionClient.FormatSubscriptionPath(subscriptionWrapper.SubscriptionDescription.TopicPath,
                                                                      subscriptionWrapper.SubscriptionDescription.Name);
         }
     }
 }
Example #12
0
        protected override async Task OnOpenAsync()
        {
            var receiverPaths = this.Settings.EntityType == EntityType.Topic ? this.Settings.SubscriptionNames.Select((n) => SubscriptionClient.FormatSubscriptionPath(this.Settings.TopicPath, n)) : new string[] { this.Settings.QueuePath };

            foreach (var receiverPath in receiverPaths)
            {
                for (int i = 0; i < this.Settings.ReceiverCount; i++)
                {
                    var factory = MessagingFactory.CreateFromConnectionString(this.ConnectionString);
                    factory.RetryPolicy = RetryPolicy.NoRetry;
                    this.Factories.Add(factory);
                    var receiver = factory.CreateMessageReceiver(receiverPath, this.Settings.ReceiveMode);
                    receiver.RetryPolicy = RetryPolicy.NoRetry;
                    this.receivers.Add(receiver);
                }
            }

            await this.receivers.First().ReceiveAsync();

            await this.receivers.ParallelForEachAsync(async (receiver, receiverIndex) =>
            {
                await Extensions.IgnoreExceptionAsync(async() => await receiver.ReceiveAsync(TimeSpan.Zero));
            });
        }
        public async Task <SubscriptionDescription> Create(string topicPath, string subscriptionName, SubscriptionMetadataInternal metadata, string sqlFilter, INamespaceManagerInternal namespaceManager, string forwardTo = null)
        {
            var subscriptionDescription = new SubscriptionDescription(topicPath, subscriptionName)
            {
                EnableBatchedOperations  = subscriptionSettings.EnableBatchedOperations,
                AutoDeleteOnIdle         = subscriptionSettings.AutoDeleteOnIdle,
                DefaultMessageTimeToLive = subscriptionSettings.DefaultMessageTimeToLive,
                EnableDeadLetteringOnFilterEvaluationExceptions = subscriptionSettings.EnableDeadLetteringOnFilterEvaluationExceptions,
                EnableDeadLetteringOnMessageExpiration          = subscriptionSettings.EnableDeadLetteringOnMessageExpiration,
                LockDuration     = subscriptionSettings.LockDuration,
                MaxDeliveryCount = DefaultMaxDeliveryCountForNoImmediateRetries
            };

            if (subscriptionSettings.ForwardDeadLetteredMessagesToCondition(SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName)))
            {
                subscriptionDescription.ForwardDeadLetteredMessagesTo = subscriptionSettings.ForwardDeadLetteredMessagesTo;
            }

            subscriptionSettings.DescriptionCustomizer(subscriptionDescription);

            if (!string.IsNullOrWhiteSpace(forwardTo))
            {
                subscriptionDescription.ForwardTo = forwardTo;
            }

            subscriptionDescription.UserMetadata = metadata.Description;

            try
            {
                if (!await ExistsAsync(topicPath, subscriptionName, metadata.Description, namespaceManager).ConfigureAwait(false))
                {
                    await namespaceManager.CreateSubscription(subscriptionDescription, sqlFilter).ConfigureAwait(false);

                    logger.Info($"Subscription '{subscriptionDescription.UserMetadata}' in namespace '{namespaceManager.Address.Host}' created as '{subscriptionDescription.Name}'.");

                    var key = GenerateSubscriptionKey(namespaceManager.Address, subscriptionDescription.TopicPath, subscriptionDescription.Name);
                    await rememberExistence.AddOrUpdate(key, keyNotFound => TaskEx.CompletedTrue, (updateTopicPath, previousValue) => TaskEx.CompletedTrue).ConfigureAwait(false);
                }
                else
                {
                    logger.Info($"Subscription '{subscriptionDescription.Name}' in namespace '{namespaceManager.Address.Host}' aka '{subscriptionDescription.UserMetadata}' already exists, skipping creation.");
                    logger.InfoFormat("Checking if subscription '{0}' in namespace '{1}' needs to be updated.", subscriptionDescription.Name, namespaceManager.Address.Host);
                    var existingSubscriptionDescription = await namespaceManager.GetSubscription(subscriptionDescription.TopicPath, subscriptionDescription.Name).ConfigureAwait(false);

                    if (MembersAreNotEqual(existingSubscriptionDescription, subscriptionDescription))
                    {
                        OverrideImmutableMembers(existingSubscriptionDescription, subscriptionDescription);
                        logger.InfoFormat("Updating subscription '{0}' in namespace '{1}' with new description.", subscriptionDescription.Name, namespaceManager.Address.Host);
                        await namespaceManager.UpdateSubscription(subscriptionDescription).ConfigureAwait(false);
                    }
                }
            }
            catch (MessagingEntityAlreadyExistsException)
            {
                // the subscription already exists or another node beat us to it, which is ok
                logger.InfoFormat("Subscription '{0}' in namespace '{1}' already exists, another node probably beat us to it.", subscriptionDescription.Name, namespaceManager.Address.Host);
            }
            catch (TimeoutException)
            {
                logger.InfoFormat("Timeout occurred on subscription creation for topic '{0}' subscription name '{1}' in namespace '{2}' going to validate if it doesn't exist.", subscriptionDescription.TopicPath, subscriptionDescription.Name, namespaceManager.Address.Host);

                // there is a chance that the timeout occurred, but the topic was still created, check again
                if (!await ExistsAsync(subscriptionDescription.TopicPath, subscriptionDescription.Name, metadata.Description, namespaceManager, removeCacheEntry: true).ConfigureAwait(false))
                {
                    throw;
                }

                logger.InfoFormat("Looks like subscription '{0}' in namespace '{1}' exists anyway.", subscriptionDescription.Name, namespaceManager.Address.Host);
            }
            catch (MessagingException ex)
            {
                var loggedMessage = $"{(ex.IsTransient ? "Transient" : "Non transient")} {ex.GetType().Name} occurred on subscription '{subscriptionDescription.Name}' creation for topic '{subscriptionDescription.TopicPath}' in namespace '{namespaceManager.Address.Host}'.";

                if (!ex.IsTransient)
                {
                    logger.Fatal(loggedMessage, ex);
                    throw;
                }

                logger.Info(loggedMessage, ex);
            }

            return(subscriptionDescription);
        }
Example #14
0
        /*private static async Task MainAsync()
         * {
         *  queueClient = new QueueClient(ServiceBusConnectionString, QueueName, ReceiveMode.PeekLock);
         *  ReceiveMessages();
         *
         *  Console.WriteLine("Press any key to stop receiving messages.");
         *  Console.ReadKey();
         *
         *  // Close the client after the ReceiveMessages method has exited.
         *  await queueClient.CloseAsync();
         * }*/

        private void GetMessages(/*bool peek, bool all, int count*/)
        {
            bool peek  = false;
            bool all   = true;
            int  count = iMessageCount;

            SetLogText("Delete Process Starts");

            try
            {
                var brokeredMessages = new List <BrokeredMessage>();
                if (peek)
                {
                    var subscriptionClient = serviceBusHelper.MessagingFactory.CreateSubscriptionClient(strTopic,
                                                                                                        strSubscription,
                                                                                                        ReceiveMode.PeekLock);
                    var totalRetrieved = 0;
                    while (totalRetrieved < count)
                    {
                        var messageEnumerable = subscriptionClient.PeekBatch(count);
                        if (messageEnumerable == null)
                        {
                            break;
                        }
                        var messageArray = messageEnumerable as BrokeredMessage[] ?? messageEnumerable.ToArray();
                        var partialList  = new List <BrokeredMessage>(messageArray);
                        brokeredMessages.AddRange(partialList);
                        totalRetrieved += partialList.Count;
                        if (partialList.Count == 0)
                        {
                            break;
                        }
                    }
                    //writeToLog(string.Format(MessagesPeekedFromTheSubscription, brokeredMessages.Count, subscriptionWrapper.SubscriptionDescription.Name));
                }
                else
                {
                    MessageReceiver messageReceiver;

                    /*if (subscriptionWrapper.SubscriptionDescription.RequiresSession)
                     * {
                     *  var subscriptionClient = serviceBusHelper.MessagingFactory.CreateSubscriptionClient(strTopic,
                     *                                                                                      strSubscription,
                     *                                                                                      ReceiveMode.ReceiveAndDelete);
                     *
                     *  messageReceiver = subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(MainForm.SingletonMainForm.ReceiveTimeout));
                     * }
                     * else*/
                    {
                        messageReceiver = serviceBusHelper.MessagingFactory.CreateMessageReceiver(SubscriptionClient.FormatSubscriptionPath(
                                                                                                      strTopic,
                                                                                                      strSubscription),
                                                                                                  ReceiveMode.ReceiveAndDelete);

                        SetLogText("Message Receiver Created");
                    }

                    SetLogText("Need to delete: " + count);
                    var totalRetrieved = 0;
                    int retrieved;
                    do
                    {
                        var messages   = messageReceiver.ReceiveBatch(10, TimeSpan.FromSeconds(1));
                        var enumerable = messages as BrokeredMessage[] ?? messages.ToArray();
                        retrieved = enumerable.Count();
                        SetLogText("Retrived: " + retrieved);

                        if (retrieved == 0)
                        {
                            continue;
                        }
                        totalRetrieved += retrieved;
                        SetMessagesDeletedText(totalRetrieved.ToString());
                        brokeredMessages.AddRange(enumerable);

                        SetProgress(retrieved);
                        SetLogText("Total Retrived: " + totalRetrieved);
                    } while (retrieved > 0 && (all || count > totalRetrieved));

                    SetMessagesDeletedText(totalRetrieved.ToString());
                    SetProgress(retrieved);
                }
                messageBindingList = new SortableBindingList <BrokeredMessage>(brokeredMessages)
                {
                    AllowEdit   = false,
                    AllowNew    = false,
                    AllowRemove = false
                };
            }
            catch (TimeoutException ex)
            {
                SetLogText("TimeoutException: " + ex.Message);
            }
            catch (NotSupportedException ex)
            {
                SetLogText("NotSupportedException: " + ex.Message);//ReadMessagesOneAtTheTime(peek, all, count, messageInspector);
            }
            catch (Exception ex)
            {
                SetLogText("Exception: " + ex.Message);//HandleException(ex);
            }
            finally
            {
                SetLogText("Process Complete !!!!!");

                /*mainTabControl.ResumeLayout();
                 * mainTabControl.ResumeDrawing();
                 * tabPageMessages.ResumeLayout();
                 * tabPageMessages.ResumeDrawing();
                 * Cursor.Current = Cursors.Default;*/
            }
        }
Example #15
0
            protected override IEnumerator <AsyncStep> GetAsyncSteps()
            {
                this.owner.namespaceManager = this.serviceBusFactory.CreateNamespaceManager();

                for (int partitionId = 0; partitionId < this.owner.partitionCount; partitionId++)
                {
                    // Create topic if not exists.
                    string topicPath = this.owner.GetTopicPath(partitionId);

                    bool topicExist = false;

                    yield return(this.CallAsync(
                                     (thisPtr, t, c, s) => thisPtr.owner.namespaceManager.BeginTopicExists(topicPath, c, s),
                                     (thisPtr, r) => topicExist = thisPtr.owner.namespaceManager.EndTopicExists(r),
                                     ExceptionPolicy.Transfer));

                    if (!topicExist)
                    {
                        TopicDescription topicDescription = new TopicDescription(topicPath);

                        yield return(this.CallAsync(
                                         (thisPtr, t, c, s) => thisPtr.owner.namespaceManager.BeginCreateTopic(topicDescription, c, s),
                                         (thisPtr, r) => topicDescription = thisPtr.owner.namespaceManager.EndCreateTopic(r),
                                         ExceptionPolicy.Transfer));
                    }

                    for (int nodeId = 0; nodeId < this.owner.nodeCount; nodeId++)
                    {
                        // Create subscriptions if not exist
                        string subscriptionName = GetSubscriptionName(nodeId);

                        bool subscriptionExists = false;

                        yield return(this.CallAsync(
                                         (thisPtr, t, c, s) => thisPtr.owner.namespaceManager.BeginSubscriptionExists(topicPath, subscriptionName, c, s),
                                         (thisPtr, r) => subscriptionExists = thisPtr.owner.namespaceManager.EndSubscriptionExists(r),
                                         ExceptionPolicy.Transfer));

                        if (!subscriptionExists)
                        {
                            SubscriptionDescription subscriptionDescription = new SubscriptionDescription(topicPath, subscriptionName)
                            {
                                RequiresSession = false
                            };

                            yield return(this.CallAsync(
                                             (thisPtr, t, c, s) => thisPtr.owner.namespaceManager.BeginCreateSubscription(subscriptionDescription, c, s),
                                             (thisPtr, r) => thisPtr.owner.namespaceManager.EndCreateSubscription(r),
                                             ExceptionPolicy.Transfer));
                        }
                    }
                }

                for (int partitionId = 0; partitionId < this.owner.partitionCount; partitionId++)
                {
                    MessagingFactory factory = null;

                    yield return(this.CallAsync(
                                     (thisPtr, t, c, s) => thisPtr.serviceBusFactory.BeginCreateMessagingFactory(c, s),
                                     (thisPtr, r) => factory = thisPtr.serviceBusFactory.EndCreateMessagingFactory(r),
                                     ExceptionPolicy.Transfer));

                    this.owner.factories.Add(partitionId, factory);

                    string topicPath              = this.owner.GetTopicPath(partitionId);
                    string subscriptionName       = GetSubscriptionName(this.owner.nodeId);
                    string subscriptionEntityPath = SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName);

                    MessageSender sender = null;

                    yield return(this.CallAsync(
                                     (thisPtr, t, c, s) => factory.BeginCreateMessageSender(topicPath, c, s),
                                     (thisPtr, r) => sender = factory.EndCreateMessageSender(r),
                                     ExceptionPolicy.Transfer));

                    this.owner.senders.Add(partitionId, sender);

                    MessageReceiver receiver = null;

                    yield return(this.CallAsync(
                                     (thisPtr, t, c, s) => factory.BeginCreateMessageReceiver(subscriptionEntityPath, ReceiveMode.ReceiveAndDelete, c, s),
                                     (thisPtr, r) => receiver = factory.EndCreateMessageReceiver(r),
                                     ExceptionPolicy.Transfer));

                    var pump = new MessagePump(topicPath, receiver, this.owner.inputQueue, this.owner.semaphore);
                    this.owner.pumps.Add(partitionId, pump);

                    pump.Start();
                }

                this.owner.dispatcher = new MessageDispatcher(this.owner.inputQueue, this.owner.onReceivedAsync);
                this.owner.dispatcher.Start();
            }
        private void GetMessages(bool peek, bool all, int count, SubscriptionWrapper SW)
        {
            try
            {
                var brokeredMessages = new List <BrokeredMessage>();
                if (peek)
                {
                    var subscriptionClient = serviceBusHelper.MessagingFactory.CreateSubscriptionClient(SW.SubscriptionDescription.TopicPath,
                                                                                                        SW.SubscriptionDescription.Name,
                                                                                                        ReceiveMode.PeekLock);
                    var totalRetrieved = 0;
                    while (totalRetrieved < count)
                    {
                        var messageEnumerable = subscriptionClient.PeekBatch(count);
                        if (messageEnumerable == null)
                        {
                            break;
                        }

                        IBrokeredMessageInspector messageInspector = null;
                        var messageArray = messageEnumerable as BrokeredMessage[] ?? messageEnumerable.ToArray();
                        var partialList  = new List <BrokeredMessage>(messageArray);

                        brokeredMessages.AddRange(partialList);
                        totalRetrieved += partialList.Count;
                        if (partialList.Count == 0)
                        {
                            break;
                        }
                        else
                        {
                            for (int iIndex = 0; iIndex < partialList.Count; iIndex++)
                            {
                                BrokeredMessage bMsg = partialList[iIndex];
                                int             x    = 0;
                            }
                        }
                    }
                    //writeToLog(string.Format(MessagesPeekedFromTheSubscription, brokeredMessages.Count, subscriptionWrapper.SubscriptionDescription.Name));
                }
                else
                {
                    MessageReceiver messageReceiver;
                    if (SW.SubscriptionDescription.RequiresSession)
                    {
                        var subscriptionClient = serviceBusHelper.MessagingFactory.CreateSubscriptionClient(SW.SubscriptionDescription.TopicPath,
                                                                                                            SW.SubscriptionDescription.Name,
                                                                                                            ReceiveMode.ReceiveAndDelete);
                        //messageReceiver = subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(MainForm.SingletonMainForm.ReceiveTimeout));
                    }
                    else
                    {
                        messageReceiver = serviceBusHelper.MessagingFactory.CreateMessageReceiver(SubscriptionClient.FormatSubscriptionPath(
                                                                                                      SW.SubscriptionDescription.TopicPath,
                                                                                                      SW.SubscriptionDescription.Name),
                                                                                                  ReceiveMode.ReceiveAndDelete);
                    }

                    //writeToLog(string.Format(MessagesReceivedFromTheSubscription, brokeredMessages.Count, subscriptionWrapper.SubscriptionDescription.Name));
                }

                if (!peek)
                {
                    /*if (OnRefresh != null)
                     * {
                     *  OnRefresh();
                     * }*/
                }
            }
            catch (TimeoutException)
            {
                /*writeToLog(string.Format(NoMessageReceivedFromTheSubscription,
                 *                       MainForm.SingletonMainForm.ReceiveTimeout,
                 *                       subscriptionWrapper.SubscriptionDescription.Name));*/

                int x = 0;
            }
        }
Example #17
0
        public ServiceBusSubscription Subscribe(IList <string> topicNames,
                                                Action <int, IEnumerable <BrokeredMessage> > handler,
                                                Action <int, Exception> errorHandler)
        {
            if (topicNames == null)
            {
                throw new ArgumentNullException("topicNames");
            }

            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            _trace.TraceInformation("Subscribing to {0} topic(s) in the service bus...", topicNames.Count);

            var subscriptions = new ServiceBusSubscription.SubscriptionContext[topicNames.Count];
            var clients       = new TopicClient[topicNames.Count];

            for (var topicIndex = 0; topicIndex < topicNames.Count; ++topicIndex)
            {
                string topicName = topicNames[topicIndex];

                if (!_namespaceManager.TopicExists(topicName))
                {
                    try
                    {
                        _trace.TraceInformation("Creating a new topic {0} in the service bus...", topicName);

                        _namespaceManager.CreateTopic(topicName);

                        _trace.TraceInformation("Creation of a new topic {0} in the service bus completed successfully.", topicName);
                    }
                    catch (MessagingEntityAlreadyExistsException)
                    {
                        // The entity already exists
                        _trace.TraceInformation("Creation of a new topic {0} threw an MessagingEntityAlreadyExistsException.", topicName);
                    }
                }

                // Create a client for this topic
                clients[topicIndex] = TopicClient.CreateFromConnectionString(_configuration.ConnectionString, topicName);

                _trace.TraceInformation("Creation of a new topic client {0} completed successfully.", topicName);

                // Create a random subscription
                string subscriptionName = Guid.NewGuid().ToString();

                try
                {
                    var subscriptionDescription = new SubscriptionDescription(topicName, subscriptionName);

                    // This cleans up the subscription while if it's been idle for more than the timeout.
                    subscriptionDescription.AutoDeleteOnIdle = IdleSubscriptionTimeout;

                    _namespaceManager.CreateSubscription(subscriptionDescription);

                    _trace.TraceInformation("Creation of a new subscription {0} for topic {1} in the service bus completed successfully.", subscriptionName, topicName);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                    // The entity already exists
                    _trace.TraceInformation("Creation of a new subscription {0} for topic {1} threw an MessagingEntityAlreadyExistsException.", subscriptionName, topicName);
                }

                // Create a receiver to get messages
                string          subscriptionEntityPath = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
                MessageReceiver receiver = _factory.CreateMessageReceiver(subscriptionEntityPath, ReceiveMode.ReceiveAndDelete);

                _trace.TraceInformation("Creation of a message receive for subscription entity path {0} in the service bus completed successfully.", subscriptionEntityPath);

                subscriptions[topicIndex] = new ServiceBusSubscription.SubscriptionContext(topicName, subscriptionName, receiver);

                var receiverContext = new ReceiverContext(topicIndex, receiver, handler, errorHandler);

                ProcessMessages(receiverContext);
            }

            _trace.TraceInformation("Subscription to {0} topics in the service bus Topic service completed successfully.", topicNames.Count);

            return(new ServiceBusSubscription(_configuration, _namespaceManager, subscriptions, clients));
        }
Example #18
0
        public async Task <SubscriptionDescription> Create(string topicPath, string subscriptionName, SubscriptionMetadataInternal metadata, string sqlFilter, INamespaceManagerInternal namespaceManager, string forwardTo)
        {
            if (!(metadata is ForwardingTopologySubscriptionMetadata meta))
            {
                throw new InvalidOperationException($"Cannot create subscription `{subscriptionName}` for topic `{topicPath}` without namespace information required.");
            }

            var subscriptionDescription = new SubscriptionDescription(topicPath, subscriptionName)
            {
                EnableBatchedOperations  = subscriptionSettings.EnableBatchedOperations,
                AutoDeleteOnIdle         = subscriptionSettings.AutoDeleteOnIdle,
                DefaultMessageTimeToLive = subscriptionSettings.DefaultMessageTimeToLive,
                EnableDeadLetteringOnFilterEvaluationExceptions = subscriptionSettings.EnableDeadLetteringOnFilterEvaluationExceptions,
                EnableDeadLetteringOnMessageExpiration          = subscriptionSettings.EnableDeadLetteringOnMessageExpiration,
                LockDuration     = subscriptionSettings.LockDuration,
                MaxDeliveryCount = DefaultMaxDeliveryCountForNoImmediateRetries
            };

            if (subscriptionSettings.ForwardDeadLetteredMessagesToCondition(SubscriptionClient.FormatSubscriptionPath(topicPath, subscriptionName)))
            {
                subscriptionDescription.ForwardDeadLetteredMessagesTo = subscriptionSettings.ForwardDeadLetteredMessagesTo;
            }

            subscriptionSettings.DescriptionCustomizer(subscriptionDescription);

            subscriptionDescription.ForwardTo    = forwardTo;
            subscriptionDescription.UserMetadata = metadata.Description;

            try
            {
                var exists = await ExistsAsync(topicPath, subscriptionName, metadata.Description, namespaceManager).ConfigureAwait(false);

                if (!exists)
                {
                    var ruleDescription = new RuleDescription
                    {
                        Filter = new SqlFilter(sqlFilter),
                        Name   = metadata.SubscriptionNameBasedOnEventWithNamespace
                    };

                    try
                    {
                        await namespaceManager.CreateSubscription(subscriptionDescription, ruleDescription).ConfigureAwait(false);

                        logger.Info($"Subscription '{subscriptionDescription.UserMetadata}' created as '{subscriptionDescription.Name}' with rule '{ruleDescription.Name}' for event '{meta.SubscribedEventFullName}' in namespace '{namespaceManager.Address.Host}'.");

                        var key = GenerateSubscriptionKey(namespaceManager.Address, subscriptionDescription.TopicPath, subscriptionDescription.Name);
                        await rememberExistence.AddOrUpdate(key, keyNotFound => TaskEx.CompletedTrue, (updateTopicPath, previousValue) => TaskEx.CompletedTrue).ConfigureAwait(false);
                    }
                    catch (MessagingEntityAlreadyExistsException)
                    {
                        // the subscription already exists or another node beat us to it, which is ok
                        logger.Info($"Subscription '{subscriptionDescription.Name}' in namespace '{namespaceManager.Address.Host}' already exists, another node probably beat us to it.");
                        exists = true;
                    }
                }

                if (exists)
                {
                    logger.Info($"Subscription '{subscriptionDescription.Name}' aka '{subscriptionDescription.UserMetadata}' already exists, skipping creation.");
                    logger.InfoFormat("Checking if subscription '{0}' in namespace '{1}' needs to be updated.", subscriptionDescription.Name, namespaceManager.Address.Host);

                    var existingSubscriptionDescription = await namespaceManager.GetSubscription(subscriptionDescription.TopicPath, subscriptionDescription.Name).ConfigureAwait(false);

                    if (MembersAreNotEqual(existingSubscriptionDescription, subscriptionDescription))
                    {
                        logger.Info($"Updating subscription '{subscriptionDescription.Name}' in namespace '{namespaceManager.Address.Host}' with new description.");
                        await namespaceManager.UpdateSubscription(subscriptionDescription).ConfigureAwait(false);
                    }

                    // Rules can't be queried, so try to add
                    var ruleDescription = new RuleDescription
                    {
                        Filter = new SqlFilter(sqlFilter),
                        Name   = metadata.SubscriptionNameBasedOnEventWithNamespace
                    };
                    logger.Info($"Adding subscription rule '{ruleDescription.Name}' for event '{meta.SubscribedEventFullName}' in namespace '{namespaceManager.Address.Host}'.");
                    try
                    {
                        var subscriptionClient = SubscriptionClient.CreateFromConnectionString(meta.NamespaceInfo.ConnectionString, topicPath, subscriptionName);
                        await subscriptionClient.AddRuleAsync(ruleDescription).ConfigureAwait(false);
                    }
                    catch (MessagingEntityAlreadyExistsException exception)
                    {
                        logger.Debug($"Rule '{ruleDescription.Name}' already exists. Response from the server: '{exception.Message}'.");
                    }
                }
            }
            catch (TimeoutException)
            {
                logger.Info($"Timeout occurred on subscription creation for topic '{subscriptionDescription.TopicPath}' subscription name '{subscriptionDescription.Name}' in namespace '{namespaceManager.Address.Host}' going to validate if it doesn't exist.");

                // there is a chance that the timeout occurred, but the topic was still created, check again
                if (!await ExistsAsync(subscriptionDescription.TopicPath, subscriptionDescription.Name, metadata.Description, namespaceManager, removeCacheEntry: true).ConfigureAwait(false))
                {
                    throw;
                }

                logger.Info($"Looks like subscription '{subscriptionDescription.Name}' in namespace '{namespaceManager.Address.Host}' exists anyway.");
            }
            catch (MessagingException ex)
            {
                var loggedMessage = $"{(ex.IsTransient ? "Transient" : "Non transient")} {ex.GetType().Name} occurred on subscription '{subscriptionDescription.Name}' creation for topic '{subscriptionDescription.TopicPath}' in namespace '{namespaceManager.Address.Host}'.";

                if (!ex.IsTransient)
                {
                    logger.Fatal(loggedMessage, ex);
                    throw;
                }

                logger.Info(loggedMessage, ex);
            }

            return(subscriptionDescription);
        }
        private async void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (btnStart.Text == StopCaption)
                {
                    await CancelActions();

                    btnStart.Text = StartCaption;
                    return;
                }

                if (serviceBusHelper != null &&
                    ValidateParameters())
                {
                    startLog?.Invoke();
                    btnStart.Enabled = false;
                    Cursor.Current   = Cursors.WaitCursor;
                    //*****************************************************************************************************
                    //                                   Retrieve Messaging Factory
                    //*****************************************************************************************************
                    var messagingFactory = serviceBusHelper.MessagingFactory;

                    //*****************************************************************************************************
                    //                                   Initialize Statistics and Manager Action
                    //*****************************************************************************************************
                    actionCount               = 0;
                    receiverMessageNumber     = 0;
                    receiverMessagesPerSecond = 0;
                    receiverMinimumTime       = long.MaxValue;
                    receiverMaximumTime       = 0;
                    receiverAverageTime       = 0;
                    receiverTotalTime         = 0;
                    if (checkBoxReceiverEnableGraph.Checked)
                    {
                        chart.Series.ToList().ForEach(s => s.Points.Clear());
                    }
                    managerResetEvent = new ManualResetEventSlim(false);
                    Action <CancellationTokenSource> managerAction = cts =>
                    {
                        if (cts == null)
                        {
                            return;
                        }
                        try
                        {
                            managerResetEvent.Wait(cts.Token);
                        }
                        catch (OperationCanceledException)
                        {
                        }
                        if (!cts.IsCancellationRequested)
                        {
                            Invoke((MethodInvoker)async delegate
                            {
                                btnStart.Text = StartCaption;
                                await MainForm.SingletonMainForm.RefreshSelectedEntity();
                            });
                        }
                    };

                    Action updateGraphAction = () =>
                    {
                        var  ok  = true;
                        long max = 10;
                        while (!graphCancellationTokenSource.IsCancellationRequested && (actionCount > 1 || ok))
                        {
                            ok = true;
                            long receiveMessageNumber = 0;
                            long receiveTotalTime     = 0;
                            while (ok && receiveMessageNumber < max)
                            {
                                ok = blockingCollection.TryTake(out var tuple, 10);
                                if (ok)
                                {
                                    receiveMessageNumber += tuple.Item1;
                                    receiveTotalTime     += tuple.Item2;
                                    if (receiveMessageNumber > max)
                                    {
                                        max = receiveMessageNumber;
                                    }
                                }
                            }
                            if (receiveMessageNumber > 0)
                            {
                                var receiveTuple = new Tuple <long, long, DirectionType>(receiveMessageNumber, receiveTotalTime, DirectionType.Receive);
                                if (InvokeRequired)
                                {
                                    Invoke(new UpdateStatisticsDelegate(InternalUpdateStatistics), receiveTuple.Item1, receiveTuple.Item2, receiveTuple.Item3);
                                }
                                else
                                {
                                    InternalUpdateStatistics(receiveTuple.Item1,
                                                             receiveTuple.Item2,
                                                             receiveTuple.Item3);
                                }
                            }
                        }
                        if (Interlocked.Decrement(ref actionCount) == 0)
                        {
                            managerResetEvent.Set();
                        }
                    };

                    AsyncCallback updateGraphCallback = a =>
                    {
                        var action = a.AsyncState as Action;
                        if (action != null)
                        {
                            action.EndInvoke(a);
                            if (Interlocked.Decrement(ref actionCount) == 0)
                            {
                                managerResetEvent.Set();
                            }
                        }
                    };

                    blockingCollection = new BlockingCollection <Tuple <long, long, DirectionType> >();
                    //*****************************************************************************************************
                    //                                   Receiving messages from a Subscription
                    //*****************************************************************************************************
                    var currentSubscription = subscriptionWrapper.SubscriptionDescription;
                    if (currentSubscription == null)
                    {
                        throw new ArgumentException(NoSubscriptionSelected);
                    }
                    var currentReceiveMode = cboReceivedMode.Text == PeekLock ?
                                             ReceiveMode.PeekLock :
                                             ReceiveMode.ReceiveAndDelete;
                    var currentMoveToDeadLetterQueue   = checkBoxMoveToDeadLetter.Checked;
                    var currentReadFromDeadLetterQueue = checkBoxReadFromDeadLetter.Checked;

                    try
                    {
                        receiverCancellationTokenSource  = new CancellationTokenSource();
                        receiverCancellationTokenSource  = new CancellationTokenSource();
                        receiverBrokeredMessageInspector = cboReceiverInspector.SelectedIndex > 0
                                                      ? Activator.CreateInstance(serviceBusHelper.BrokeredMessageInspectors[cboReceiverInspector.Text]) as IBrokeredMessageInspector
                                                      : null;

                        Action <int> receiverAction = taskId =>
                        {
                            var allSessionsAccepted = false;

                            while (!allSessionsAccepted)
                            {
                                try
                                {
                                    MessageReceiver messageReceiver;
                                    if (currentReadFromDeadLetterQueue)
                                    {
                                        messageReceiver =
                                            messagingFactory.CreateMessageReceiver(SubscriptionClient.FormatDeadLetterPath(currentSubscription.TopicPath,
                                                                                                                           currentSubscription.Name),
                                                                                   currentReceiveMode);
                                    }
                                    else
                                    {
                                        if (currentSubscription.RequiresSession)
                                        {
                                            var subscriptionClient = messagingFactory.CreateSubscriptionClient(currentSubscription.TopicPath,
                                                                                                               currentSubscription.Name,
                                                                                                               currentReceiveMode);
                                            messageReceiver = subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(sessionTimeout));
                                        }
                                        else
                                        {
                                            messageReceiver = messagingFactory.CreateMessageReceiver(SubscriptionClient.FormatSubscriptionPath(currentSubscription.TopicPath,
                                                                                                                                               currentSubscription.Name),
                                                                                                     currentReceiveMode);
                                        }
                                    }
                                    messageReceiver.PrefetchCount = prefetchCount;
                                    string traceMessage;
                                    if (checkBoxReceiverUseTransaction.Checked)
                                    {
                                        using (var scope = new TransactionScope())
                                        {
                                            serviceBusHelper.ReceiveMessages(messageReceiver,
                                                                             taskId,
                                                                             receiveTimeout,
                                                                             filter,
                                                                             currentMoveToDeadLetterQueue,
                                                                             checkBoxCompleteReceive.Checked,
                                                                             checkBoxDeferMessage.Checked,
                                                                             checkBoxEnableReceiverLogging.Checked,
                                                                             checkBoxReceiverVerboseLogging.Checked,
                                                                             checkBoxReceiverEnableStatistics.Checked,
                                                                             checkBoxReceiveBatch.Checked,
                                                                             receiverBatchSize,
                                                                             checkBoxReceiverThinkTime.Checked,
                                                                             receiverThinkTime,
                                                                             receiverBrokeredMessageInspector,
                                                                             UpdateStatistics,
                                                                             receiverCancellationTokenSource,
                                                                             out traceMessage);
                                            var builder = new StringBuilder(traceMessage);
                                            if (checkBoxReceiverCommitTransaction.Checked)
                                            {
                                                scope.Complete();
                                                builder.AppendLine(TransactionCommitted);
                                            }
                                            else
                                            {
                                                builder.AppendLine(TransactionAborted);
                                            }
                                            traceMessage = builder.ToString();
                                        }
                                    }
                                    else
                                    {
                                        serviceBusHelper.ReceiveMessages(messageReceiver,
                                                                         taskId,
                                                                         receiveTimeout,
                                                                         filter,
                                                                         currentMoveToDeadLetterQueue,
                                                                         checkBoxCompleteReceive.Checked,
                                                                         checkBoxDeferMessage.Checked,
                                                                         checkBoxEnableReceiverLogging.Checked,
                                                                         checkBoxReceiverVerboseLogging.Checked,
                                                                         checkBoxReceiverEnableStatistics.Checked,
                                                                         checkBoxReceiveBatch.Checked,
                                                                         receiverBatchSize,
                                                                         checkBoxReceiverThinkTime.Checked,
                                                                         receiverThinkTime,
                                                                         receiverBrokeredMessageInspector,
                                                                         UpdateStatistics,
                                                                         receiverCancellationTokenSource,
                                                                         out traceMessage);
                                    }
                                    if (!string.IsNullOrWhiteSpace(traceMessage))
                                    {
                                        writeToLog(traceMessage.Substring(0, traceMessage.Length - 1));
                                    }
                                    allSessionsAccepted = !currentSubscription.RequiresSession;
                                }
                                catch (TimeoutException ex)
                                {
                                    if (currentSubscription.RequiresSession)
                                    {
                                        writeToLog(string.Format(NoMoreSessionsToAccept, taskId));
                                        allSessionsAccepted = true;
                                    }
                                    else
                                    {
                                        HandleException(ex);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    HandleException(ex);
                                }
                            }
                        };

                        // Define Receiver AsyncCallback
                        AsyncCallback receiverCallback = a =>
                        {
                            var action = a.AsyncState as Action <int>;
                            if (action != null)
                            {
                                action.EndInvoke(a);
                                if (Interlocked.Decrement(ref actionCount) == 0)
                                {
                                    managerResetEvent.Set();
                                }
                            }
                        };

                        // Start Receiver Actions
                        for (var i = 0; i < receiverTaskCount; i++)
                        {
                            receiverAction.BeginInvoke(i, receiverCallback, receiverAction);
                            Interlocked.Increment(ref actionCount);
                        }
                    }
                    catch (Exception ex)
                    {
                        HandleException(ex);
                    }
                    if (actionCount > 0)
                    {
                        managerCancellationTokenSource = new CancellationTokenSource();
                        managerAction.BeginInvoke(managerCancellationTokenSource, null, null);
                        graphCancellationTokenSource = new CancellationTokenSource();
                        updateGraphAction.BeginInvoke(updateGraphCallback, updateGraphAction);
                        Interlocked.Increment(ref actionCount);
                        btnStart.Text = StopCaption;
                    }
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                btnStart.Enabled = true;
                Cursor.Current   = Cursors.Default;
            }
        }
        public ServiceBusSubscription Subscribe(IList <string> topicNames,
                                                Action <int, IEnumerable <BrokeredMessage> > handler,
                                                Action <int, Exception> errorHandler)
        {
            if (topicNames == null)
            {
                throw new ArgumentNullException("topicNames");
            }

            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            var subscriptions = new ServiceBusSubscription.SubscriptionContext[topicNames.Count];
            var clients       = new TopicClient[topicNames.Count];

            for (var topicIndex = 0; topicIndex < topicNames.Count; ++topicIndex)
            {
                string topicName = topicNames[topicIndex];

                if (!_namespaceManager.TopicExists(topicName))
                {
                    try
                    {
                        _namespaceManager.CreateTopic(topicName);
                    }
                    catch (MessagingEntityAlreadyExistsException)
                    {
                        // The entity already exists
                    }
                }

                // Create a client for this topic
                clients[topicIndex] = TopicClient.CreateFromConnectionString(_configuration.ConnectionString, topicName);

                // Create a random subscription
                string subscriptionName = Guid.NewGuid().ToString();

                try
                {
                    _namespaceManager.CreateSubscription(topicName, subscriptionName);
                }
                catch (MessagingEntityAlreadyExistsException)
                {
                    // The entity already exists
                }

                // Create a receiver to get messages
                string          subscriptionEntityPath = SubscriptionClient.FormatSubscriptionPath(topicName, subscriptionName);
                MessageReceiver receiver = _factory.CreateMessageReceiver(subscriptionEntityPath, ReceiveMode.ReceiveAndDelete);

                subscriptions[topicIndex] = new ServiceBusSubscription.SubscriptionContext(topicName, subscriptionName, receiver);

                var receiverContext = new ReceiverContext(topicIndex, receiver, handler, errorHandler);

                ProcessMessages(receiverContext);
            }

            return(new ServiceBusSubscription(_configuration, _namespaceManager, subscriptions, clients));
        }