Class SheetParallel
Reads a sheet of any format across several threads: ParseAsync yields typed rows in source
order, ForEachAsync hands each row to a callback on the worker threads, and
AggregateAsync folds rows into one accumulator per partition.
public static class SheetParallel
- Inheritance
-
SheetParallel
- Inherited Members
Remarks
The caller owns the workbook and keeps it open until the returned task completes or the enumeration ends. The CSV dialect is the CsvReaderOptions the workbook was opened with.
A read falls back to one sequential pass, with the same results and no error, when DegreeOfParallelism is 1, the sheet is too small to partition usefully, the sheet is an XLS sheet or a table view, or a CSV cannot be partitioned (a stream that is not a file or a non-UTF-8 encoding).
Delivery guarantees. The general contract is the weaker CSV one: ForEachAsync is at-least-once,
and a partition whose start was guessed wrongly is discarded and read again. XLSB delivers every row
exactly once, in ForEachAsync too. XLSX delivers exactly once for a well-formed sheet; a
malformed one can make ForEachAsync deliver a row twice. ParseAsync yields the same items in
the same order as the sequential ExcelParser<T> on every format, and
AggregateAsync and ForEachAsync equal their own single-thread run.
Row: ParseAsync renumbers it from the count emitted at the
merge; ForEachAsync and AggregateAsync report the exact row when sequential and 0 when partitioned.
Methods
AggregateAsync<TState>(IExcelSheet, RowAggregation<TState>, SheetParallelOptions?, CancellationToken)
Reads a sheet across several threads and folds every row with the functions of
aggregation, one accumulator per partition, combined in sheet order.
public static Task<TState> AggregateAsync<TState>(IExcelSheet sheet, RowAggregation<TState> aggregation, SheetParallelOptions? options = null, CancellationToken ct = default)
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the task completes.
aggregationRowAggregation<TState>The seed, accumulate and combine functions. They carry the same contract as IRowAccumulator<TSelf, TModel>.
optionsSheetParallelOptionsParallelism and header options. Defaults to Default.
ctCancellationTokenA token to cancel processing.
Returns
- Task<TState>
The combined accumulator.
Type Parameters
TStateThe accumulator type.
Remarks
Carries the same fallbacks as the IRowAccumulator<TSelf, TModel> overloads.
Exceptions
- ArgumentNullException
sheetoraggregation, or one of its functions, is null.- ArgumentOutOfRangeException
A numeric option is negative.
AggregateAsync<TAccumulator, TModel>(IExcelSheet, ExcelParser<TModel>, SheetParallelOptions?, CancellationToken)
Reads a sheet across several threads, binds every row to a TModel
through parser and folds it into a TAccumulator, one
instance per partition, merged in sheet order.
public static Task<TAccumulator> AggregateAsync<TAccumulator, TModel>(IExcelSheet sheet, ExcelParser<TModel> parser, SheetParallelOptions? options = null, CancellationToken ct = default) where TAccumulator : IRowAccumulator<TAccumulator, TModel>, new() where TModel : allows ref struct
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the task completes.
parserExcelParser<TModel>How columns bind to
TModel; created with ExcelParser. Its HeaderRow is ignored in favour of HeaderRow.optionsSheetParallelOptionsParallelism and header options. Defaults to Default.
ctCancellationTokenA token to cancel processing.
Returns
- Task<TAccumulator>
The accumulator holding every record.
Type Parameters
TAccumulatorThe accumulator type. See IRowAccumulator<TSelf, TModel> for the contract it must honor.
TModelThe model type.
Remarks
The header is bound once, before any row is folded. A property that fails to parse keeps its
default unless ThrowOnParseFailure is set; a missing
[ExcelRequired] column or value throws ExcelParseException; empty rows are skipped.
Row is exact when the sheet is read sequentially and 0 when it is partitioned, since a partition does not know how many rows precede it.
Otherwise carries the same contract and fallbacks as the IRowRecord<TSelf> overload.
Exceptions
- ArgumentNullException
sheetorparseris null.- ArgumentException
parserbinds columns by header name and HeaderRow is 0.- ArgumentOutOfRangeException
A numeric option is negative.
AggregateAsync<TAccumulator, TRecord>(IExcelSheet, SheetParallelOptions?, CancellationToken)
Reads a sheet across several threads, parses every row into a TRecord
and folds it into a TAccumulator, one instance per partition, merged in sheet order.
public static Task<TAccumulator> AggregateAsync<TAccumulator, TRecord>(IExcelSheet sheet, SheetParallelOptions? options = null, CancellationToken ct = default) where TAccumulator : IRowAccumulator<TAccumulator, TRecord>, new() where TRecord : IRowRecord<TRecord>, allows ref struct
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the task completes.
optionsSheetParallelOptionsParallelism and header options. Defaults to Default.
ctCancellationTokenA token to cancel processing.
Returns
- Task<TAccumulator>
The accumulator holding every record.
Type Parameters
TAccumulatorThe accumulator type. See IRowAccumulator<TSelf, TModel> for the contract it must honor.
TRecordThe record type. A record whose TryParse(Row, out TSelf) returns false is skipped.
Remarks
A partition read from a wrongly guessed start is read again into a new accumulator. The result holds every record exactly once, but TryParse(Row, out TSelf) and Add(TModel) may already have run for the discarded pass's records, as IRowAccumulator<TSelf, TModel> describes. A sequential fallback uses a single accumulator and never calls Merge(TSelf).
Exceptions
- ArgumentNullException
sheetis null.- ArgumentOutOfRangeException
A numeric option is negative.
ForEachAsync<TModel>(IExcelSheet, ExcelParser<TModel>, Action<TModel>, SheetParallelOptions?, CancellationToken)
Reads a sheet across several threads, binds every row to a TModel
through parser and hands it to body.
public static Task ForEachAsync<TModel>(IExcelSheet sheet, ExcelParser<TModel> parser, Action<TModel> body, SheetParallelOptions? options = null, CancellationToken ct = default) where TModel : allows ref struct
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the task completes.
parserExcelParser<TModel>How columns bind to
TModel; created with ExcelParser. Its HeaderRow is ignored in favour of HeaderRow.bodyAction<TModel>Receives each record. See the remarks for the contract it must honor.
optionsSheetParallelOptionsParallelism and header options. Defaults to Default.
ctCancellationTokenA token to cancel processing.
Returns
- Task
A task that completes when every record has been delivered.
Type Parameters
TModelThe model type. May be a
ref structwith ReadOnlySpan<T> of byte properties.
Remarks
Carries the same concurrency, delivery and span-lifetime contract as the
IRowRecord<TSelf> overload: body runs concurrently, delivery is
at least once in general (exactly once on XLSB, and on a well-formed XLSX sheet), and records arrive
in no particular order. A property that fails to parse keeps its default unless
ThrowOnParseFailure is set; a missing [ExcelRequired] column or
value throws ExcelParseException; empty rows are skipped.
Row is exact when the sheet is read sequentially and 0 when it is partitioned, since a partition does not know how many rows precede it.
Exceptions
- ArgumentNullException
sheet,parserorbodyis null.- ArgumentException
parserbinds columns by header name and HeaderRow is 0.- ArgumentOutOfRangeException
A numeric option is negative.
ForEachAsync<TRecord>(IExcelSheet, Action<TRecord>, SheetParallelOptions?, CancellationToken)
Reads a sheet across several threads, parses every row into a TRecord
and hands it to body.
public static Task ForEachAsync<TRecord>(IExcelSheet sheet, Action<TRecord> body, SheetParallelOptions? options = null, CancellationToken ct = default) where TRecord : IRowRecord<TRecord>, allows ref struct
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the task completes.
bodyAction<TRecord>Receives each record. See the remarks for the contract it must honor.
optionsSheetParallelOptionsParallelism and header options. Defaults to Default.
ctCancellationTokenA token to cancel processing.
Returns
- Task
A task that completes when every record has been delivered.
Type Parameters
TRecordThe record type. A record whose TryParse(Row, out TSelf) returns false is skipped.
Remarks
body runs concurrently on worker threads and must be safe to call from
several at once; the caller owns any synchronization. Records arrive in no particular order.
Delivery is at least once in general: body may be invoked more than once for the
same record. On CSV, a partition whose start was guessed wrongly is read again from the confirmed
offset, and the discarded speculative pass may already have delivered a whole partition's worth of
records, which may also be misparsed: a wrong start shifts every field boundary. An exception
body throws during a discarded pass is discarded with it. A start is only guessed
wrongly inside a quoted field, so a CSV in which the quote character never appears delivers every
record exactly once. XLSB delivers every row exactly once. XLSX does too for a well-formed sheet; on
a malformed one, workers may already have called body for rows that are then
dropped, so a row can be delivered twice or be one the sequential reader would not produce.
A body with side effects must therefore be idempotent and tolerate records that
do not exist. For exactly-once on any source, use
AggregateAsync<TAccumulator, TRecord>(IExcelSheet, SheetParallelOptions?, CancellationToken), where the
discarded partition's accumulator is thrown away, and apply the side effects once it returns.
A ReadOnlySpan<T> column points into a pooled buffer the worker reuses once
body returns. Copy anything that must outlive the call.
Exceptions
- ArgumentNullException
sheetorbodyis null.- ArgumentOutOfRangeException
A numeric option is negative.
ParseAsync<T>(IExcelSheet, ExcelParser<T>, SheetParallelOptions?, CancellationToken)
Parses a sheet into T instances across several threads, yielding the
same sequence, in the same order, that the sequential ExcelParser<T> produces.
public static IAsyncEnumerable<T> ParseAsync<T>(IExcelSheet sheet, ExcelParser<T> parser, SheetParallelOptions? options = null, CancellationToken ct = default)
Parameters
sheetIExcelSheetThe sheet to read. The caller keeps ownership and keeps its workbook open until the enumeration ends.
parserExcelParser<T>How columns bind to
T; created with ExcelParser. Its HeaderRow locates the header.optionsSheetParallelOptionsParallelism options. Defaults to Default. HeaderRow does not apply here and must be left at
0.ctCancellationTokenA token to cancel enumeration.
Returns
- IAsyncEnumerable<T>
An enumerable that yields one
Tper data row.
Type Parameters
TThe row model type to bind each row to.
Remarks
Parsing and type conversion run in parallel; whatever the caller does per row does not. A caller whose per-row work dominates will see little gain from raising DegreeOfParallelism. For CSV, ExcelReader.Core.Reader.Csv.CsvReaderOptions.InternStrings yields substantially less here than sequentially, since each partition keeps its own dedup cache. A partition read from a wrongly guessed start is discarded before any of its rows are yielded, but its cells have already passed through the parser's converters and property setters, which must therefore be free of side effects.
Exceptions
- ArgumentNullException
sheetorparseris null.- ArgumentException
HeaderRow is not 0.
- ArgumentOutOfRangeException
A numeric option is negative.