public Task ExportAsync(CancellationToken cancellationToken, Action <int> reportProgress) { this.cancellationToken = cancellationToken; this.ReportProgress = reportProgress ?? delegate { }; tcs = new TaskCompletionSource <bool>(); writer = new CsvWriter(stream); extractor = new DocumentColumnsExtractor(columns); writer.WriteHeaderRecord(columns.Select(c => c.Header)); FetchNextPage(); return(tcs.Task); }
public async Task ExportAsync(CancellationToken cancellationToken, Action <int> reportProgress) { reportProgress = reportProgress ?? delegate { }; var context = SynchronizationContext.Current; using (stream) using (var writer = new CsvWriter(stream)) { var extractor = new DocumentColumnsExtractor(columns); writer.WriteHeaderRecord(columns.Select(c => c.Header)); // we do the streaming of documents on a background thread mainly to escape the // SynchronizationContext: when there's no synchronization context involved the // async methods can resume on any thread instead of having to hop back to the UI thread. // This avoids massive overheads await TaskEx.Run(async() => { var totalResults = new Reference <long>(); using (var documentsStream = await collectionSource.StreamAsync(totalResults)) { IList <JsonDocument> documentBatch; var fetchedDocuments = 0; do { documentBatch = await GetNextBatch(documentsStream, cancellationToken); fetchedDocuments += documentBatch.Count; // extracting properties from the documents has to be done on the UI thread // because it might involve using FrameworkElements and Silverlight databinding context.Send(delegate { WriteColumnsForDocuments(writer, documentBatch, extractor); reportProgress((int)(((double)fetchedDocuments / totalResults.Value) * 100)); }, null); } while (documentBatch.Count > 0); } }, cancellationToken); } }
private void WriteColumnsForDocuments(CsvWriter writer, IEnumerable <JsonDocument> documents, DocumentColumnsExtractor extractor) { foreach (var document in documents) { var values = extractor.GetValues(document); writer.WriteDataRecord(values); } }