private void UploadEvents(object context)
        {
            // Get the event source
            EventSource eventSource = context as EventSource;

            // Create and initialize the uploader
            AzureTableQueryableEventUploader uploader = CreateAndInitializeUploader();

            // Provide the uploader with the ETW manifest cache
            uploader.SetEtwManifestCache(manifestCache);

            // Inform the uploader that we're about to deliver ETW events to it
            uploader.OnEtwEventProcessingPeriodStart();

            // Deliver the ETW events to the uploader
            EventRecord eventRecord;
            bool        result = eventSource.GetNextEvent(out eventRecord);

            while (result)
            {
                uploader.OnEtwEventsAvailable(new EventRecord[] { eventRecord });
                eventSource.FreeEventBuffers(eventRecord);
                result = eventSource.GetNextEvent(out eventRecord);
            }

            // Inform the uploader that we're done delivering ETW events to it
            uploader.OnEtwEventProcessingPeriodStop();

            // Dispose the uploader
            uploader.Dispose();
        }
        public void QueryableEventUploadTest()
        {
            // Initialize last FMM event timestamp to a value that
            // will prevent the uploaders from performing old entity
            // deletion
            Utility.LastFmmEventTimestamp = DateTime.MinValue;

            // Upload events to table
            Thread idBasedUploader1   = new Thread(this.UploadEvents);
            Thread idBasedUploader2   = new Thread(this.UploadEvents);
            Thread nonIdBasedUploader = new Thread(this.UploadEvents);

            DateTime              startTime        = DateTime.UtcNow.AddMinutes(-1 * StartTimeOffsetMinutes);
            IdBasedEventSource    idBasedSource    = new IdBasedEventSource(providerId, startTime);
            NonIdBasedEventSource nonIdBasedSource = new NonIdBasedEventSource(providerId, startTime);

            idBasedUploader1.Start(idBasedSource);
            idBasedUploader2.Start(idBasedSource);
            nonIdBasedUploader.Start(nonIdBasedSource);

            idBasedUploader1.Join();
            idBasedUploader2.Join();
            nonIdBasedUploader.Join();

            // Verify that the events were uploaded successfully
            idBasedSource.VerifyUpload(tableClient);
            nonIdBasedSource.VerifyUpload(tableClient);

            // Delete old events from table

            // Initialize last FMM event timestamp to a value that
            // will cause the uploader to perform old entity deletion
            Utility.LastFmmEventTimestamp = DateTime.UtcNow;

            // Deletion routine will run approximately one minute after we create the uploader below
            DateTime deletionRoutineRunTime = DateTime.UtcNow.AddMinutes(1);

            // Figure out - approximately - the cut-off time computed by the deletion routine
            DateTime deletionCutoffTime = deletionRoutineRunTime.AddMinutes(-1 * EntityDeletionAgeMinutes);

            // Since the cut-off time prediction is only approximate, add buffers
            DateTime deletionCutoffTimeLow  = deletionCutoffTime.AddMinutes(-1 * DeletionCutoffTimeBufferMinutes);
            DateTime deletionCutoffTimeHigh = deletionCutoffTime.AddMinutes(DeletionCutoffTimeBufferMinutes);

            // Create an uploader to perform the deletion
            AzureTableQueryableEventUploader uploader = CreateAndInitializeUploader();

            int  deletionWaitTimeSeconds = 150;
            bool verifyDeletionResult    = false;
            int  verificationAttempts    = 0;

            while (deletionWaitTimeSeconds > 0)
            {
                // Sleep for a while to allow the deletion routine to run
                Thread.Sleep(deletionWaitTimeSeconds * 1000);

                // Check if the deletion is complete
                verificationAttempts++;
                Utility.TraceSource.WriteInfo(
                    AzureTableUploaderTest.TraceType,
                    "Attempt {0}: Verifying old entity deletion ...",
                    verificationAttempts);
                verifyDeletionResult = idBasedSource.VerifyDeletion(tableClient, deletionCutoffTimeLow, deletionCutoffTimeHigh);
                verifyDeletionResult = verifyDeletionResult && nonIdBasedSource.VerifyDeletion(tableClient, deletionCutoffTimeLow, deletionCutoffTimeHigh);

                if (verifyDeletionResult)
                {
                    Utility.TraceSource.WriteInfo(
                        AzureTableUploaderTest.TraceType,
                        "Finished verifying old entity deletion.");
                    break;
                }
                else
                {
                    Utility.TraceSource.WriteInfo(
                        AzureTableUploaderTest.TraceType,
                        "Old entity deletion is either incomplete or unsuccessful. Will verify again after a while, if we have not reached the limit for verification attempts.");
                }

                // The next wait time will be shorter
                deletionWaitTimeSeconds = deletionWaitTimeSeconds / 2;
            }

            // Dispose the uploader
            uploader.Dispose();

            if (false == verifyDeletionResult)
            {
                Utility.TraceSource.WriteError(
                    AzureTableUploaderTest.TraceType,
                    "Old entites have not been deleted as expected. We have reached the limit for verification attempts.");
                Verify.Fail("Old entity deletion failed");
            }
        }