// ReSharper disable once FunctionComplexityOverflow
        private async void btnStart_Click(object sender, EventArgs e)
        {
            if (string.Compare(btnStart.Text, Start, StringComparison.OrdinalIgnoreCase) == 0)
            {
                if (startLog != null && checkBoxLogging.Checked)
                {
                    startLog();
                }
                receiverEventDataInspector = cboReceiverInspector.SelectedIndex > 0
                                           ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboReceiverInspector.Text]) as IEventDataInspector
                                           : null;

                cancellationTokenSource = new CancellationTokenSource();
                btnStart.Text = Stop;
                blockingCollection = new BlockingCollection<Tuple<long, long, long>>();
                timer = new System.Timers.Timer
                {
                    AutoReset = true,
                    Enabled = true,
                    Interval = 1000 * txtRefreshInformation.IntegerValue
                };
                timer.Elapsed += timer_Elapsed;
                var ns = serviceBusHelper != null && !string.IsNullOrWhiteSpace(serviceBusHelper.Namespace) ? serviceBusHelper.Namespace : iotHubConnectionString;
                var eventHub = eventHubClient.Path;
                var maxBatchSize = txtMaxBatchSize.IntegerValue > 0 ? txtMaxBatchSize.IntegerValue : 1;
                var receiveTimeout = TimeSpan.FromSeconds(txtReceiveTimeout.IntegerValue);
                try
                {
                    registeredDictionary = new Dictionary<string, bool>(partitionRuntumeInformationList.Count);
                    var startDateTimeEnabled = pickerStartingDateTimeUtc.Checked;
                    var startDateTimeValue = DateTime.SpecifyKind(pickerStartingDateTimeUtc.Value, DateTimeKind.Utc);
                    var eventProcessorOptions = new EventProcessorOptions
                    {
                        InitialOffsetProvider = partitionId =>
                        {
                            if (startDateTimeEnabled)
                            {
                                return startDateTimeValue;
                            }
                            var lease = EventProcessorCheckpointHelper.GetLease(ns,
                                eventHub,
                                consumerGroup.GroupName,
                                partitionId);
                            return lease != null ? lease.Offset : "-1";
                        },
                        MaxBatchSize = maxBatchSize,
                        ReceiveTimeOut = receiveTimeout
                    };
                    eventProcessorOptions.ExceptionReceived += (s, ex) => HandleException(ex.Exception);
                    var checkpointManager = new EventProcessorCheckpointManager
                    {
                        Namespace = ns,
                        EventHub = eventHub,
                        ConsumerGroup = consumerGroup.GroupName
                    };
                    var eventProcessorFactoryConfiguration = new EventProcessorFactoryConfiguration(checkBoxLogging,
                                                                                                    checkBoxTrackMessages,
                                                                                                    checkBoxVerbose,
                                                                                                    checkBoxOffsetInclusive,
                                                                                                    checkBoxCheckpoint,
                                                                                                    cancellationTokenSource.Token)
                    {
                        TrackEvent = ev => Invoke(new Action<EventData>(m => eventDataCollection.Add(m)), ev),
                        GetElapsedTime = GetElapsedTime,
                        UpdateStatistics = UpdateStatistics,
                        WriteToLog = writeToLog,
                        MessageInspector = receiverEventDataInspector,
                        ServiceBusHelper = serviceBusHelper
                    };
                    foreach (var partitionRuntimeInformation in partitionRuntumeInformationList)
                    {
#pragma warning disable 4014
                        consumerGroup.RegisterProcessorFactoryAsync(
#pragma warning restore 4014
EventProcessorCheckpointHelper.GetLease(ns, eventHub, consumerGroup.GroupName, partitionRuntimeInformation.PartitionId),
                                checkpointManager,
                                new EventProcessorFactory<EventProcessor>(eventProcessorFactoryConfiguration),
                                eventProcessorOptions);
                        registeredDictionary.Add(partitionRuntimeInformation.PartitionId, true);
                    }
#pragma warning disable 4014
                    Task.Run(new Action(RefreshGraph));
#pragma warning restore 4014
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    StopListenerAsync().Wait();
                    btnStart.Text = Start;
                }
            }
            else
            {
                try
                {
                    await StopListenerAsync();
                    btnStart.Text = Start;
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }
        /// <summary>
        /// This method can be used to send multiple messages to a queue or a topic.
        /// </summary>
        /// <param name="eventHubClient">An EventHubClient object used to send messages.</param>
        /// <param name="eventDataTemplateEnumerable">A collection of message templates to use to clone messages from.</param>
        /// <param name="getMessageNumber">This function returns the message number.</param>
        /// <param name="messageCount">The total number of messages to send.</param>
        /// <param name="taskId">The sender task id.</param>
        /// <param name="updatePartitionKey">Indicates whether to use a unique template key for each message.</param>
        /// <param name="addMessageNumber">Indicates whether to add a message number property.</param>
        /// <param name="logging">Indicates whether to enable logging of message content and properties.</param>
        /// <param name="verbose">Indicates whether to enable verbose logging.</param>
        /// <param name="statistics">Indicates whether to enable sender statistics.</param>
        /// <param name="eventDataInspector">Event Data inspector.</param>
        /// <param name="updateStatistics">When statistics = true, this delegate is invoked to update statistics.</param>
        /// <param name="sendBatch">Indicates whether to use SendBatch.</param>
        /// <param name="senderThinkTime">Indicates whether to use think time.</param>
        /// <param name="thinkTime">Indicates the value of the sender think time.</param>
        /// <param name="batchSize">Indicates the batch size.</param>
        /// <param name="cancellationTokenSource">The cancellation token.</param>
        /// <returns>Trace message.</returns>
        public async Task<string> SendEventData(EventHubClient eventHubClient,
                                                IEnumerable<EventData> eventDataTemplateEnumerable,
                                                Func<long> getMessageNumber,
                                                long messageCount,
                                                int taskId,
                                                bool updatePartitionKey,
                                                bool addMessageNumber,
                                                bool logging,
                                                bool verbose,
                                                bool statistics,
                                                bool sendBatch,
                                                int batchSize,
                                                bool senderThinkTime,
                                                int thinkTime,
                                                IEventDataInspector eventDataInspector,
                                                UpdateStatisticsDelegate updateStatistics,
                                                CancellationTokenSource cancellationTokenSource)
        {
            if (eventHubClient == null)
            {
                throw new ArgumentNullException(EventHubClientCannotBeNull);
            }

            if (eventDataTemplateEnumerable == null)
            {
                throw new ArgumentNullException(EventDataTemplateEnumerableCannotBeNull);
            }

            if (cancellationTokenSource == null)
            {
                throw new ArgumentNullException(CancellationTokenSourceCannotBeNull);
            }

            var eventDataCircularList = new CircularList<EventData>(eventDataTemplateEnumerable);

            long messagesSent = 0;
            long totalElapsedTime = 0;
            long minimumSendTime = long.MaxValue;
            long maximumSendTime = 0;
            string exceptionMessage = null;
            try
            {
                if (sendBatch && batchSize > 1)
                {
                    //var more = true;
                    //while (!cancellationTokenSource.Token.IsCancellationRequested && more)
                    //{
                    //    var eventDataList = new List<EventData>();
                    //    var messageNumberList = new List<long>();
                    //    while (!cancellationTokenSource.Token.IsCancellationRequested &&
                    //           messageNumberList.Count < batchSize && more)
                    //    {
                    //        messageNumber = getMessageNumber();
                    //        if (messageNumber < messageCount)
                    //        {
                    //            messageNumberList.Add(messageNumber);
                    //        }
                    //        else
                    //        {
                    //            more = false;
                    //        }
                    //    }
                    //    if (messageNumberList.Count > 0)
                    //    {
                    //        long elapsedMilliseconds = 0;
                    //        await RetryHelper.RetryActionAsync(async () =>
                    //        {
                    //            for (var i = 0; i < messageNumberList.Count; i++)
                    //            {
                    //                eventDataList.Add(eventDataInspector != null?
                    //                                  eventDataInspector.BeforeSendMessage(eventDataCircularList.Next.Clone()) :
                    //                                  eventDataCircularList.Next.Clone());
                    //                if (addMessageNumber)
                    //                {
                    //                    eventDataList[i].Properties[MessageNumber] = messageNumberList[i];
                    //                }
                    //            }
                    //            if (messageNumberList.Count > 0)
                    //            {
                    //                elapsedMilliseconds = await SendEventDataBatch(eventHubClient,
                    //                                                               eventDataList,
                    //                                                               messageNumberList,
                    //                                                               taskId,
                    //                                                               logging,
                    //                                                               verbose);
                    //            }
                    //        },
                    //        writeToLog);
                    //        messagesSent += eventDataList.Count;
                    //        if (elapsedMilliseconds > maximumSendTime)
                    //        {
                    //            maximumSendTime = elapsedMilliseconds;
                    //        }
                    //        if (elapsedMilliseconds < minimumSendTime)
                    //        {
                    //            minimumSendTime = elapsedMilliseconds;
                    //        }
                    //        totalElapsedTime += elapsedMilliseconds;
                    //        if (statistics)
                    //        {
                    //            updateStatistics(eventDataList.Count, elapsedMilliseconds, DirectionType.Send);
                    //        }
                    //    }
                    //    if (senderThinkTime)
                    //    {
                    //        WriteToLog(string.Format(SleepingFor, thinkTime));
                    //        Thread.Sleep(thinkTime);
                    //    }
                    //}
                }
                else
                {
                    long messageNumber;
                    while ((messageNumber = getMessageNumber()) < messageCount &&
                       !cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        long elapsedMilliseconds = 0;
                        long number = messageNumber;
                        await RetryHelper.RetryActionAsync(async () =>
                        {
                            var eventData = eventDataInspector != null ?
                                            eventDataInspector.BeforeSendMessage(eventDataCircularList.Next.Clone()) :
                                            eventDataCircularList.Next.Clone();
                            if (addMessageNumber)
                            {
                                // ReSharper disable AccessToModifiedClosure
                                eventData.Properties[MessageNumber] = number;
                                // ReSharper restore AccessToModifiedClosure
                            }

                            elapsedMilliseconds = await SendEventData(eventHubClient,
                                                                      eventData,
                                                                      number,
                                                                      taskId,
                                                                      logging,
                                                                      verbose);
                        },
                        writeToLog);
                        messagesSent++;
                        if (elapsedMilliseconds > maximumSendTime)
                        {
                            maximumSendTime = elapsedMilliseconds;
                        }
                        if (elapsedMilliseconds < minimumSendTime)
                        {
                            minimumSendTime = elapsedMilliseconds;
                        }
                        totalElapsedTime += elapsedMilliseconds;
                        if (statistics)
                        {
                            updateStatistics(1, elapsedMilliseconds, DirectionType.Send);
                        }
                        if (senderThinkTime)
                        {
                            WriteToLog(string.Format(SleepingFor, thinkTime));
                            Thread.Sleep(thinkTime);
                        }
                    }
                }
            }
            catch (ServerBusyException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (MessageLockLostException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (CommunicationObjectAbortedException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (CommunicationObjectFaultedException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (CommunicationException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (TimeoutException ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            catch (Exception ex)
            {
                eventHubClient.Abort();
                exceptionMessage = ex.Message;
            }
            var averageSendTime = messagesSent > 0 ? totalElapsedTime / messagesSent : maximumSendTime;
            // ReSharper disable RedundantCast
            var messagesPerSecond = totalElapsedTime > 0 ? (double)(messagesSent * 1000) / (double)totalElapsedTime : 0;
            // ReSharper restore RedundantCast
            var builder = new StringBuilder();
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatisticsHeader,
                                             taskId));
            if (!string.IsNullOrWhiteSpace(exceptionMessage))
            {
                builder.AppendLine(exceptionMessage);
                throw new Exception(builder.ToString());
            }
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine1,
                                             messagesSent,
                                             messagesPerSecond,
                                             totalElapsedTime));
            builder.AppendLine(string.Format(CultureInfo.CurrentCulture,
                                             SenderStatitiscsLine2,
                                             averageSendTime,
                                             minimumSendTime == long.MaxValue ? 0 : minimumSendTime,
                                             maximumSendTime));
            return builder.ToString();
        }
Пример #3
0
 public EventProcessor()
 {
     this.cancellationTokenSource = new CancellationTokenSource();
     this.eventDataInspector      = new LogEventDataInspector();
     this.eventDataInspector.StartTask(cancellationTokenSource.Token, Filter.Path);
 }
 public EventProcessor()
     {
         this.cancellationTokenSource = new CancellationTokenSource();
         this.eventDataInspector = new LogEventDataInspector();
         this.eventDataInspector.StartTask(cancellationTokenSource.Token, Filter.Path);
     }
        private async void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (btnStart.Text == StopCaption)
                {
                    await CancelActions();
                    btnStart.Text = StartCaption;
                    return;
                }

                if (serviceBusHelper != null &&
                    ValidateParameters())
                {
                    if (startLog != null)
                    {
                        startLog();
                    }
                    btnStart.Enabled = false;
                    Cursor.Current = Cursors.WaitCursor;

                    //*****************************************************************************************************
                    //                                   Initialize Statistics and Manager Action
                    //*****************************************************************************************************
                    actionCount = 0;
                    senderMessageNumber = 0;
                    senderMessagesPerSecond = 0;
                    senderMinimumTime = long.MaxValue;
                    senderMaximumTime = 0;
                    senderAverageTime = 0;
                    senderTotalTime = 0;

                    lblSenderLastTime.Text = string.Empty;
                    lblSenderAverageTime.Text = string.Empty;
                    lblSenderMaximumTime.Text = string.Empty;
                    lblSenderMinimumTime.Text = string.Empty;
                    lblSenderMessagesPerSecond.Text = string.Empty;
                    lblSenderMessageNumber.Text = string.Empty;

                    if (checkBoxSenderEnableGraph.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) delegate { btnStart.Text = StartCaption; });
                        }
                    };

                    Action updateGraphAction = () =>
                    {
                        var ok = true;
                        long max = 10;
                        while (!graphCancellationTokenSource.IsCancellationRequested && (actionCount > 1 || ok))
                        {
                            ok = true;
                            long sendMessageNumber = 0;
                            long sendTotalTime = 0;
                            while (ok && sendMessageNumber < max)
                            {
                                Tuple<long, long, DirectionType> tuple;
                                ok = blockingCollection.TryTake(out tuple, 10);
                                if (ok)
                                {
                                    sendMessageNumber += tuple.Item1;
                                    sendTotalTime += tuple.Item2;
                                    if (sendMessageNumber > max)
                                    {
                                        max = sendMessageNumber;
                                    }
                                }
                            }
                            if (sendMessageNumber > 0)
                            {
                                var sendTuple = new Tuple<long, long, DirectionType>(sendMessageNumber, sendTotalTime, DirectionType.Send);
                                if (InvokeRequired)
                                {
                                    Invoke(new UpdateStatisticsDelegate(InternalUpdateStatistics),
                                        new object[]
                                        {
                                            sendTuple.Item1,
                                            sendTuple.Item2,
                                            sendTuple.Item3
                                        });
                                }
                                else
                                {
                                    InternalUpdateStatistics(sendTuple.Item1,
                                        sendTuple.Item2,
                                        sendTuple.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>>();

                    //*****************************************************************************************************
                    //                                   Sending messages to a EventHub
                    //*****************************************************************************************************

                    if (eventDataCount > 0)
                    {
                        // Create event hub clients. They are cached for later usage to improve performance.
                        if (isSenderFaulted ||
                            eventHubClientCollection == null ||
                            eventHubClientCollection.Count == 0 ||
                            eventHubClientCollection.Count < senderTaskCount)
                        {
                            eventHubClientCollection = new List<EventHubClient>(senderTaskCount);
                            var amqpConnectionString = GetAmqpConnectionString(serviceBusHelper.ConnectionString);
                            for (var i = 0; i < senderTaskCount; i++)
                            {
                                eventHubClientCollection.Add(EventHubClient.CreateFromConnectionString(amqpConnectionString, eventHubDescription.Path));
                            }
                            isSenderFaulted = false;
                        }

                        // Create outbound message template list
                        var eventDataTemplateList = new List<EventData>();
                        var updatePartitionKey = checkBoxUpdatePartitionKey.Checked;
                        var noPartitionKey = checkBoxNoPartitionKey.Checked;
                        if (messageTabControl.SelectedIndex == MessageTabPage)
                        {
                            eventDataTemplateList.Add(serviceBusHelper.CreateEventDataTemplate(txtMessageText.Text,
                                                                                               GetPartitionKey(),
                                                                                               bindingSource.Cast<MessagePropertyInfo>()));

                        }
                        else if (messageTabControl.SelectedIndex == FilesTabPage)
                        {
                            updatePartitionKey = !radioButtonJsonTemplate.Checked && !radioButtonXmlTemplate.Checked &&
                                                 checkBoxUpdatePartitionKey.Checked;
                            var fileList = messageFileListView.Items.Cast<ListViewItem>()
                                .Where(i => i.Checked)
                                .Select(i => i.Text)
                                .ToList();
                            if (fileList.Count == 0)
                            {
                                writeToLog(NoMessageSelected);
                                return;
                            }
                            foreach (var fileName in fileList)
                            {
                                try
                                {
                                    using (var streamReader = new StreamReader(fileName))
                                    {
                                        var text = streamReader.ReadToEnd();
                                        EventData template;
                                        if (radioButtonBinaryFile.Checked)
                                        {
                                            using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                                            {
                                                using (var binaryReader = new BinaryReader(fileStream))
                                                {
                                                    var bytes = binaryReader.ReadBytes((int) fileStream.Length);
                                                    template = serviceBusHelper.CreateEventDataTemplate(new MemoryStream(bytes),
                                                                                                        GetPartitionKey(), 
                                                                                                        bindingSource.Cast<MessagePropertyInfo>());
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (radioButtonTextFile.Checked)
                                            {
                                                template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>());
                                            }
                                            else if (radioButtonJsonTemplate.Checked)
                                            {
                                                try
                                                {
                                                    var eventDataTemplate = JsonSerializerHelper.Deserialize<EventDataTemplate>(text);
                                                    template = serviceBusHelper.CreateEventDataTemplate(eventDataTemplate);
                                                }
                                                catch (Exception)
                                                {
                                                    writeToLog(string.Format(InvalidJsonTemplate, fileName));
                                                    template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>());
                                                }
                                            }
                                            else // XML Template
                                            {
                                                try
                                                {
                                                    var eventDataTemplate = XmlSerializerHelper.Deserialize<EventDataTemplate>(text);
                                                    template = serviceBusHelper.CreateEventDataTemplate(eventDataTemplate);
                                                }
                                                catch (Exception)
                                                {
                                                    writeToLog(string.Format(InvalidXmlTemplate, fileName));
                                                    template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>());
                                                }
                                            }
                                        }
                                        if (template != null)
                                        {
                                            eventDataTemplateList.Add(template);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    HandleException(ex);
                                }
                            }
                        }
                        else // Event Data Generator Tab
                        {
                            try
                            {
                                senderEventDataGenerator = eventDataGeneratorPropertyGrid.SelectedObject as IEventDataGenerator;
                                if (senderEventDataGenerator != null)
                                {
                                    eventDataTemplateList = new List<EventData>(senderEventDataGenerator.GenerateEventDataCollection(txtMessageCount.IntegerValue, writeToLog));
                                }
                            }
                            catch (Exception ex)
                            {
                                HandleException(ex);
                            }
                        }
                        try
                        {
                            senderCancellationTokenSource = new CancellationTokenSource();
                            currentIndex = 0;
                            senderEventDataInspector = cboSenderInspector.SelectedIndex > 0
                                                         ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboSenderInspector.Text]) as IEventDataInspector
                                                         : null;

                            Func<long> getMessageNumber = () =>
                            {
                                lock (this)
                                {
                                    return currentIndex++;
                                }
                            };
                            Action<int, IEnumerable<EventData>> senderAction =
                                (taskId, messageTemplateEnumerable) =>
                                {
                                    try
                                    {
                                        var traceMessage = serviceBusHelper.SendEventData(eventHubClientCollection[taskId],
                                                                                            messageTemplateEnumerable,
                                                                                            getMessageNumber,
                                                                                            eventDataCount,
                                                                                            taskId,
                                                                                            updatePartitionKey,
                                                                                            noPartitionKey,
                                                                                            checkBoxAddMessageNumber.Checked,
                                                                                            checkBoxEnableSenderLogging.Checked,
                                                                                            checkBoxSenderVerboseLogging.Checked,
                                                                                            checkBoxSenderEnableStatistics.Checked,
                                                                                            checkBoxSendBatch.Checked,
                                                                                            senderBatchSize,
                                                                                            checkBoxSenderThinkTime.Checked,
                                                                                            senderThinkTime,
                                                                                            senderEventDataInspector,
                                                                                            UpdateStatistics,
                                                                                            senderCancellationTokenSource,
                                                                                            partitionDescription != null ?
                                                                                            partitionDescription.PartitionId :
                                                                                            null).Result;
                                        if (!string.IsNullOrWhiteSpace(traceMessage))
                                        {
                                            writeToLog(traceMessage.Substring(0, traceMessage.Length - 1));
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        isSenderFaulted = true;
                                        HandleException(ex);
                                    }
                                };

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

                            // Start Sender Actions
                            for (var i = 0; i < Math.Min(eventDataCount, senderTaskCount); i++)
                            {
                                senderAction.BeginInvoke(i, eventDataTemplateList, senderCallback, senderAction);
                                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;
            }
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (string.Compare(btnStart.Text, Start, StringComparison.OrdinalIgnoreCase) == 0)
            {
                receiverEventDataInspector = cboReceiverInspector.SelectedIndex > 0
                                           ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboReceiverInspector.Text]) as IEventDataInspector
                                           : null;

                cancellationTokenSource = new CancellationTokenSource();
                btnStart.Text = Stop;
                blockingCollection = new BlockingCollection<Tuple<long, long, long>>();
                timer = new System.Timers.Timer
                {
                    AutoReset = true,
                    Enabled = true,
                    Interval = 1000 * txtRefreshInformation.IntegerValue
                };
                timer.Elapsed += timer_Elapsed;
                logging = checkBoxLogging.Checked;
                verbose = checkBoxVerbose.Checked;
                tracking = checkBoxTrackMessages.Checked;
                graph = checkBoxGraph.Checked;
                try
                {
                    foreach (var partitionDescription in partitionDescriptions)
                    {
                        var description = partitionDescription;
                        Task.Run(async () =>
                        {
                            try
                            {
                                var eventHubClient = EventHubClient.CreateFromConnectionString(GetAmqpConnectionString(serviceBusHelper.ConnectionString),
                                                                                               consumerGroupDescription.EventHubPath);
                                var consumerGroup = string.Compare(consumerGroupDescription.Name,
                                                                   DefaultConsumerGroupName,
                                                                   StringComparison.InvariantCultureIgnoreCase) == 0
                                                                   ? eventHubClient.GetDefaultConsumerGroup()
                                                                   : eventHubClient.GetConsumerGroup(consumerGroupDescription.Name);
                                var epoch = txtEpoch.IntegerValue;
                                var eventHubReceiver = epoch == 0 ? 
                                                        await consumerGroup.CreateReceiverAsync(description.PartitionId, txtOffset.Text, checkBoxOffsetInclusive.Checked) :
                                                        await consumerGroup.CreateReceiverAsync(description.PartitionId, txtOffset.Text, checkBoxOffsetInclusive.Checked, epoch);
                                eventHubReceiver.PrefetchCount = txtPrefetchCount.IntegerValue;
                                var received = 0;
                                EventData previousEventData = null;
                                while (!cancellationTokenSource.Token.IsCancellationRequested)
                                {
                                    var stopwatch = Stopwatch.StartNew();
                                    var eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(txtReceiveTimeout.IntegerValue));
                                    stopwatch.Stop();
                                    if (eventData == null)
                                    {
                                        if (previousEventData != null && checkpoint)
                                        {
                                            checkpointMethodInfo.Invoke(eventHubReceiver, new object[] { previousEventData });
                                            previousEventData = null;
                                            if (logging)
                                            {
                                                writeToLog(string.Format(CheckPointExecuted, description.PartitionId));
                                            }
                                        }
                                        continue;
                                    }
                                    previousEventData = eventData;
                                    if (receiverEventDataInspector != null)
                                    {
                                        eventData = receiverEventDataInspector.AfterReceiveMessage(eventData);
                                    }
                                    received++;
                                    if (logging)
                                    {
                                        var builder = new StringBuilder(string.Format(EventDataSuccessfullyReceived,
                                                                        string.IsNullOrWhiteSpace(eventData.PartitionKey)
                                                                            ? NullValue
                                                                            : eventData.PartitionKey,
                                                                        eventData.Offset,
                                                                        eventData.EnqueuedTimeUtc));
                                        if (verbose)
                                        {
                                            serviceBusHelper.GetMessageAndProperties(builder, eventData);
                                        }
                                        writeToLog(builder.ToString());
                                    }
                                    if (tracking)
                                    {
                                        eventDataCollection.Add(eventData);
                                    }
                                    if (graph)
                                    {
                                        var bodySize = (long)0;
                                        var bodyStream = eventData.GetBodyStream();
                                        if (bodyStream != null && bodyStream.CanSeek)
                                        {
                                            bodySize = bodyStream.Length;
                                        }
                                        UpdateStatistics(1, stopwatch.ElapsedMilliseconds, bodySize);
                                    }
                                    if (received == checkpointCount && checkpoint)
                                    {
                                        checkpointMethodInfo.Invoke(eventHubReceiver, new object[] { eventData });
                                        received = 0;
                                        if (logging)
                                        {
                                            writeToLog(string.Format(CheckPointExecuted, description.PartitionId));
                                        }
                                    }
                                }
                            }
                            catch (TimeoutException)
                            { }
                            catch (Exception ex)
                            {
                                HandleException(ex);
                            }
                        });
                    }
                    #pragma warning disable 4014
                    Task.Run(new Action(RefreshGraph));
                    #pragma warning restore 4014
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    StopListener();
                    btnStart.Text = Start;
                }
            }
            else
            {
                try
                {
                    StopListener();
                    btnStart.Text = Start;
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }