Это очень странная ситуация, сначала код...
Код
private List<DispatchInvoiceCTNDataModel> WorksheetToDataTableForInvoiceCTN(ExcelWorksheet excelWorksheet, int month, int year)
{
int totalRows = excelWorksheet.Dimension.End.Row;
int totalCols = excelWorksheet.Dimension.End.Column;
DataTable dt = new DataTable(excelWorksheet.Name);
// for (int i = 1; i <= totalRows; i++)
Parallel.For(1, totalRows + 1, (i) =>
{
DataRow dr = null;
if (i > 1)
{
dr = dt.Rows.Add();
}
for (int j = 1; j <= totalCols; j++)
{
if (i == 1)
{
var colName = excelWorksheet.Cells[i, j].Value.ToString().Replace(" ", String.Empty);
lock (lockObject)
{
if (!dt.Columns.Contains(colName))
dt.Columns.Add(colName);
}
}
else
{
dr[j - 1] = excelWorksheet.Cells[i, j].Value != null ? excelWorksheet.Cells[i, j].Value.ToString() : null;
}
}
});
var excelDataModel = dt.ToList<DispatchInvoiceCTNDataModel>();
// now we have mapped everything expect for the IDs
excelDataModel = MapInvoiceCTNIDs(excelDataModel, month, year, excelWorksheet);
return excelDataModel;
}
Проблема
Когда я запускаю код в случайном случае, он бросает IndexOutOfRangeException
на строку
dr[j - 1] = excelWorksheet.Cells[i, j].Value != null ? excelWorksheet.Cells[i, j].Value.ToString() : null;
Для некоторого случайного значения i
и j
. Когда я перешагиваю код (F10
), так как он запущен в ParallelLoop, некоторые другие потоки и другое исключение - это throw, что другое исключение - это что-то вроде (я не мог воспроизвести его, он просто появился один раз, но Я думаю, что это также связано с этой проблемой с потоками) Column 31 not found in excelWorksheet
. Я не понимаю, как могло произойти какое-либо из этих исключений?
case 1 IndexOutOfRangeException
также не должен появляться, поскольку единственная переменная кода/общей переменной dt
, которую я заблокировал при доступе к ней, остальное все либо является локальным, либо параметром, поэтому не должно быть проблем, связанных с потоком. Кроме того, если я проверяю значение i
или j
в окне отладки или даже оцениваю это целое выражение dr[j - 1] = excelWorksheet.Cells[i, j].Value != null ? excelWorksheet.Cells[i, j].Value.ToString() : null;
или его часть в окне отладки, то он работает отлично, никаких ошибок или ничего.
case 2
Для второй ошибки (которая, к сожалению, не воспроизводится сейчас, но все же) она не должна происходить, поскольку в excel есть 33 столбца.
Подробнее Код
В случае, если кому-то может понадобиться, как этот метод был вызван
using (var xlPackage = new ExcelPackage(viewModel.postedFile.InputStream))
{
ExcelWorksheets worksheets = xlPackage.Workbook.Worksheets;
// other stuff
var entities = this.WorksheetToDataTableForInvoiceCTN(worksheets[1], viewModel.Month, viewModel.Year);
// other stuff
}
Другое
Если кому-то нужно больше кода/деталей, дайте мне знать.
Обновление
Хорошо, чтобы ответить на некоторые комментарии. Он работает нормально при использовании цикла for
, я тестировал это много раз. Кроме того, нет особого значения i
или j
, для которого выбрано исключение. Иногда это 8, 6
, в другое время это может быть что угодно, скажем 19,2
или что-то еще. Кроме того, в цикле Parallel
+1
не наносит никакого ущерба, поскольку в документации msdn указано, что оно является эксклюзивным не включенным. Кроме того, если бы это была проблема, я бы только получал исключение в последнем индексе (последнее значение i), но это не так.
ОБНОВЛЕНИЕ 2
Данный ответ для блокировки кода
dr = dt.Rows.Add();
Я изменил его на
lock(lockObject) {
dr = dt.Rows.Add();
}
Он не работает. Теперь я получаю ArgumentOutOfRangeException
, но если я запустил это в окне отладки, он просто отлично работает.
Обновление 3
Вот полная информация о подробностях, после обновления 2 (я получаю это в строке, о которой я упоминал в обновлении 2)
System.ArgumentOutOfRangeException was unhandled by user code
HResult=-2146233086
Message=Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
Source=mscorlib
ParamName=index
StackTrace:
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Data.RecordManager.NewRecordBase()
at System.Data.DataTable.NewRecordFromArray(Object[] value)
at System.Data.DataRowCollection.Add(Object[] values)
at AdminEntity.BAL.Service.ExcelImportServices.<>c__DisplayClass2e.<WorksheetToDataTableForInvoiceCTN>b__2d(Int32 i) in C:\Projects\Manager\Admin\AdminEntity\AdminEntity.BAL\Service\ExcelImportServices.cs:line 578
at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
InnerException: