Reputation: 2908
I'm struggling to understand what is going on with this code. I've done async/await for a while now but haven't stumbled on this issue before (unless I'm just not seeing what I've done)
I'm loading a CSV file into a DataTable then I want to pull the list of column names from the DataTable to manipulate later.
In the first method, I load the CSV async then assign the DataGrid to view the data. I wasn't able to use the _ColumnList = ... in the first method because for whatever reason, the "_dtSampleCSV.Columns" did not resolve; it's not seeing that it's a DataTable.
So I moved that line to another method where it pulls the column names and assigns those names to another DataGrid. When it hits this method, there's no data in the _dtSampleCSV DataTable (no rows, no columns), yet the first DataGrid does populate with data.
I've always assumed that using an "await" waits for the thread to complete before proceeding. So either that's not true, or the thread did complete but the DataTable wasn't assigned yet.
I can only assume the data doesn't exist at that point, but the DataGrid's source is set so when the data is populated; it shows. But how do I prevent execution if await isn't completing the dataload into the DataTable?
private DataTable _dtSampleCSV = new DataTable();
private List<string> _ColumnList = new List<string>();
private async void btnAdd_Click(object sender, RoutedEventArgs e)
{
spNew.Visibility = Visibility.Visible;
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
{
tbFilePath.Text = openFileDialog.FileName;
var _dtSampleCSV = await LoadCSVAsync(openFileDialog.FileName);
dgCSVExample.DataContext = _dtSampleCSV;
dgCSVExample.Visibility = Visibility.Visible;
SetColumnGrid();
}
}
private void SetColumnGrid()
{
_ColumnList = (from DataColumn dc in _dtSampleCSV.Columns.Cast<DataColumn>() select dc.ColumnName).ToList();
dgColumnNames.DataContext = _ColumnList; // breakpoint set here to look at _dtSampleCSV and no data exists at runtime
dgColumnNames.Visibility = Visibility.Visible;
}
// csv method
public static async Task<DataTable> LoadCSVAsync(string filePath)
{
using (var reader = File.OpenText(filePath))
{
var fileText = await reader.ReadToEndAsync();
using (TextReader sr = new StringReader(fileText))
{
var adapter = new GenericParsing.GenericParserAdapter(sr);
adapter.FirstRowHasHeader = true;
adapter.MaxBufferSize = 4096;
adapter.MaxRows = 3;
DataTable dtProcess = adapter.GetDataTable();
return dtProcess;
}
}
}
Upvotes: 0
Views: 424
Reputation: 31198
Your LoadCSVAsync
method is static
, which explains why it can't access the _dtSampleCSV
instance field.
Your btnAdd_Click
method creates a local variable called _dtSampleCSV
, assigns that to the dgCSVExample.DataContext
, and then throws it away. Data from that local variable will not be available in the _dtSampleCSV
field.
Change your method so that it assigns the data to the field, rather than creating a local variable:
// Remove this:
// var _dtSampleCSV = await LoadCSVAsync(openFileDialog.FileName);
// Use this:
_dtSampleCSV = await LoadCSVAsync(openFileDialog.FileName);
NB: You should try to avoid async void
methods wherever possible.
Upvotes: 1