public static void Parse <T1, T2>( BackgroundWorker worker, string[] filePaths, string name, FilterRowAndGetProductName <T1, T2> FilterRowAndGetProductName, FilterRows <T1, T2> FilterRows, out string productName, out List <T2> records) where T1 : class { productName = null; records = new List <T2>(); worker.ReportProgress(0); for (int i = 0; i < filePaths.Length; i++) { if (worker.CancellationPending) { productName = null; records = null; return; } try { using (TextReader textReader = new StreamReader(filePaths[i])) { var engine = new FileHelperAsyncEngine <T1>(); using (engine.BeginReadStream(textReader)) { // Parse the first row from input CSV file T1 csvRow = engine.ReadNext(); if (csvRow == null) { // There is no data rows in this CSV file -- just skip it continue; } // Remove extra columns and get the product name string thisProductName; T2 filteredRow = FilterRowAndGetProductName(csvRow, out thisProductName); // Check the product name consistency if (productName != null && thisProductName != productName) { string msg = string.Format( "The selected {0} CSV File(s) do not conform to each other by \"ProductName\" column.", name); MessageBox.Show( msg, formText, MessageBoxButtons.OK, MessageBoxIcon.Error); productName = null; records = null; return; } // Save the first row data productName = thisProductName; records.Add(filteredRow); // Parse all other rows from the CSV file lazily IEnumerable <T1> csvRows = engine.AsEnumerable <T1>(); // Remove extra columns lazily IEnumerable <T2> filteredRows = FilterRows(csvRows); // Add new rows to the common list records.AddRange(filteredRows); } } } catch (Exception ex) { MessageBox.Show( ex.Message, formText, MessageBoxButtons.OK, MessageBoxIcon.Error); productName = null; records = null; return; } worker.ReportProgress(i + 1); } }