Sylvan.Data.Excel icon indicating copy to clipboard operation
Sylvan.Data.Excel copied to clipboard

Ole2Package+Ole2Stream abruptly quits when reading an XLS from a FileStream in a Blazor Server app

Open CaiusJard opened this issue 1 year ago • 3 comments

I've a problem reading a particular, reasonably sized (700kb, 2600 rows) file in a Blazor server app. I've done various tests of changing the problem file and project type:

  • a new "hello world" XLS file reads OK in the BS app
  • the problem file works OK in a Console app
  • but the combination of problem file+Blazor Server fails.

It's like an exception is thrown that kills the background reading thread, and the exception is silently swallowed. When debugging, I get to line 136 of the Ole2Stream class, there's a ReadAsync, and stepping over it manifests the problem; the yellow bar disappears and never returns no matter how long it's left..

Here's the code, and debug prints (some added by me):

image

The red box delineates the first time round that position increments from 0; this operation finishes OK. Another read occurs with a bigger buffer, and position starts from 0 again; the code reaches the ReadAsync and starts doing it (I assume) but the call never returns and no exception is thrown. The app remains running.

To repro the problem create a new Blazor Server project, and Install/add/reference Sylvan Excel by package or code. Open the Counter.razor page and add these two lines to the IncrementCount() method.

        using var fs = new FileStream(@"C:\temp\problem.xls", FileMode.Open, FileAccess.Read, FileShare.Read, 128 * 1024);
        using var edr = ExcelDataReader.Create(fs, ExcelWorkbookType.Excel);

I'll email the problem.xls file over..

CaiusJard avatar Aug 10 '22 13:08 CaiusJard

Incidentally, if I swap to using a syncronous Read() instead, I don't get a problem

CaiusJard avatar Aug 10 '22 14:08 CaiusJard

As another aside; it seems if I bufffer the entire file into a memory stream before I read (and get sylvan to read from the MS), I don't get a problem; there may be nothing Sylvan can do to resolve this*, if it's a manifestation of the runtime disposing of the filestream before sylvan's done reading it (*or maybe the fault is mine in terms of how I've decided to read the file being incompatible with BSS)

CaiusJard avatar Aug 10 '22 14:08 CaiusJard

I know exactly what's happening. This is because I don't fully/correctly support async in this library yet. At a minimum, I need to add .ConfigureAwait(false) to every async callsite. This is specifically what is causing the problem you are seeing, which is a deadlock. Apparently, blazor server runs in a single threaded environment under a synchronization context. Without the ConfigureAwait(false) async operations will trivially deadlock in such an environment.

Beyond that, here is additional work that I need to investigate with respect to handling .xlsx files asynchronously. This is one of the things that I want to complete before I move to a 1.0 release, but I don't have a roadmap or a timeline for getting that done.

In the meantime, it sounds like you have a workaround: read the whole file into memory first, which can be done asynchronously using the file IO apis.

MarkPflug avatar Aug 10 '22 14:08 MarkPflug