CsvHelper
CsvHelper copied to clipboard
Never returns when using GetRecordsAsync
Describe the bug
I output a file using the library. No problems. I try to read the same file to the same data structure. Program is stuck on GetRecordsAsync endlessly.
To Reproduce
As stated above. Really simple use case.
Switching to GetRecords works so it's clearly not any issues on my end.
Expected behavior
Should work.
There is absolutely no circumstance where a library should just hold a thread forever. If there is an error, bubble it up. Never use infinite loops.
Needless to say, after spending ages dealing with this, I'm very frustrated.
Can you give a small example that reproduces this?
private async Task SaveAsync()
{
var directory = Path.GetDirectoryName(Filename);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using var stream = new StreamWriter(Filename);
using var csvWriter = new CsvWriter(stream, CultureInfo.InvariantCulture);
await csvWriter.WriteRecordsAsync(_data);
}
public static async Task<VocabularyUserData> LoadAsync()
{
if (File.Exists(Filename))
{
using var stream = new StreamReader(Filename);
using var csvReader = new CsvReader(stream, CultureInfo.InvariantCulture);
return new VocabularyUserData(await csvReader.GetRecordsAsync<VocabularyUserDataItem>().ToListAsync());
}
else
{
return new VocabularyUserData(new List<VocabularyUserDataItem>());
}
}
private class VocabularyUserDataItem
{
public string Kanji { get; set; }
public DateTime LastAnswered { get; set; }
public int Rank { get; set; }
}
I'm saving the file using SaveAsync so only CSV Helper is interacting with the file (so the format can't be wrong).
I've debugged it a fair bit so I can confirm it's the GetRecordsAsync and not anywhere else that it is getting stuck.
Now also experiencing lock ups during save.
And the data was lost despite failing to save.
Try putting brackets in for your using blocks.
using var stream = new StreamWriter(Filename);
using var csvWriter = new CsvWriter(stream, CultureInfo.InvariantCulture);
{
await csvWriter.WriteRecordsAsync(_data);
}
This won't make a difference. Even before the new using syntax was implemented, having no braces would be equivalent to the following:
using (var stream = new StreamWriter(Filename))
{
using (var csvWriter = new CsvWriter(stream, CultureInfo.InvariantCulture))
{
await csvWriter.WriteRecordsAsync(_data);
}
}
I'm not able to reproduce the issue.
Here is my test code.
async Task Main()
{
var records = new List<VocabularyUserDataItem>();
for (var i = 0; i < 1_000_000; i++)
{
var row = i + 1;
records.Add(new VocabularyUserDataItem
{
Kanji = $"row {i}",
LastAnswered = DateTime.Now,
Rank = row,
});
}
var path = @"C:\Users\narsh\Documents\issue-1751.csv";
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
};
using (var stream = File.Open(path, FileMode.Create))
using (var writer = new StreamWriter(stream))
using (var csv = new CsvWriter(writer, config))
{
await csv.WriteRecordsAsync(records);
}
}
private class VocabularyUserDataItem
{
public string Kanji { get; set; }
public DateTime LastAnswered { get; set; }
public int Rank { get; set; }
}
Your code is not similar to mine.
Also this issue is for GetRecordsAsync not write.
Oops. You mentioned saving issues so I got that mixed up.
This works for me. Can you update this so it fails?
async Task Main()
{
var path = @"C:\Users\narsh\Documents\issue-1751.csv";
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
};
using var reader = new StreamReader(path);
using var csv = new CsvReader(reader, config);
var records = await csv.GetRecordsAsync<VocabularyUserDataItem>().ToListAsync();
}
private class VocabularyUserDataItem
{
public string Kanji { get; set; }
public DateTime LastAnswered { get; set; }
public int Rank { get; set; }
}
@JoshClose I also tried your code for async but does not work gives error.
Error CS1061 'IAsyncEnumerable<VocabularyUserDataItem>' does not contain a definition for 'ToListAsync' and no accessible extension method 'ToListAsync' accepting a first argument of type 'IAsyncEnumerable<VocabularyUserDataItem>' could be found (are you missing a using directive or an assembly reference?)
CSVHelper version 27.2.1 dotnet version 6.0
I am also experiencing this issue for csv.GetRecordsAsync(...) CSVHelper version 27.2.1 dotnet version 6.0
@Alik2015 ToListAsync is a part of System.Linq in assembly System.Linq.Async.
If someone can give me a unit test that produces the issue, I'll take a look at it. Right now I can't reproduce it.
Same issue. Never returns. No error message. csv file is 13kb.
Edit: I have a similar issue with stream.CopyToAsync which isn't a part of csvhelper, so beginning to think this is a signalR issue.
Edit 2: I believe I found the issue. If this is happening to you when reading a memory stream directly from a blazor file input (such as was the case with me), it will cause significant memory issues. See [here].(https://docs.microsoft.com/en-us/aspnet/core/blazor/file-uploads?view=aspnetcore-5.0&pivots=server) The Getrecordsasync method works fine after this.
I believe the folks in this issue are experiencing a deadlock caused by running in a SynchronizationContext (blazor server, or window GUI app for example). There are a few missing ConfigureAwait(false) calls in the code that I think are the culprits. PR #2007 should hopefully resolve it.
I am still seeing the issue with version 30.0.1 on .NET7. Getting null from "GetRecordsAsync". No error with "GetRecords" method Anyone else?