/// <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(); }