每次读取Excel工作表时使用并行foreach的不同结果

Imports System.IO Imports System.Threading Imports System.Threading.Tasks Imports System.Collections.Concurrent Imports Excel = Microsoft.Office.Interop.Excel Public Class TestCarDatas Public Property RowID As Integer Public Property ModelYear As Integer Public Property VehMfcName As String Public Property EmgVeh As Boolean End Class Module ExcelParallelDataGather2 Public Const ExcelVehDataPath As String = "D:\Users\Dell\Desktop" Public rwl As New System.Threading.ReaderWriterLock() Public rwl_writes As Integer = 0 Public FullTestVehData As New List(Of TestCarDatas)() Public x1App As New Excel.Application Public x1Workbook As Excel.Workbook Public x1Worksheet1 As Excel.Worksheet Public x1WkshtLrow As Integer Sub main() x1App.Visible = False ErrorNotify = False Console.WriteLine("Excel Parallel foreach operation program....") Dim cki As ConsoleKeyInfo x1Workbook = x1App.Workbooks.Open(Path.Combine(ExcelVehDataPath, "TestCarDatabase2014.xls"), , True) x1Worksheet1 = x1Workbook.Sheets(1) Do Console.WriteLine("Press escape key to exit, 'a' key to reiterate, 'c' key to clear console") cki = Console.ReadKey() If Chr(cki.Key).ToString = "A" Then Console.WriteLine("--> Processing...") FullTestVehData.Clear() rwl_writes = 0 Parallel.ForEach(Partitioner.Create(11, x1WkshtLrow + 1), _ Function() ' Initialize the local states Return New List(Of TestCarDatas)() End Function, _ Function(partrange, loopState, localState) ' Accumulate the thread-local computations in the loop body localState = populateCardata(x1Worksheet1, partrange.Item1, partrange.Item2) Return (localState) End Function, _ Sub(finalstate) ' Combine all local states Try rwl.AcquireWriterLock(Timeout.Infinite) Try ' It is safe for this thread to read or write ' from the shared resource in this block FullTestVehData.AddRange(finalstate) Interlocked.Increment(rwl_writes) Finally ' Ensure that the lock is released. rwl.ReleaseWriterLock() End Try Catch ex As ApplicationException ' The writer lock request timed out. End Try End Sub) End If If Chr(cki.Key).ToString = "C" Then Console.Clear() Console.WriteLine("Excel Parallel foreach operation program....") End If If Chr(cki.Key).ToString <> "A" And Chr(cki.Key).ToString <> "C" And _ cki.Key <> ConsoleKey.Escape Then Console.WriteLine("") Console.WriteLine("Invalid response via key press") End If Loop While (cki.Key <> ConsoleKey.Escape) End Sub Friend Function populateCardata(ByVal WksheetObj As Excel.Worksheet, ByVal rngStart As Integer, _ ByVal rngStop As Integer) As List(Of TestCarDatas) Dim wkrng(12) As String Dim PartVehData As New List(Of TestCarDatas) PartVehData.Clear() For i As Integer = rngStart To rngStop - 1 Dim data As New TestCarDatas For j As Integer = 0 To 12 wkrng(j) = WksheetObj.Cells(i, j + 1).Address(RowAbsolute:=False, ColumnAbsolute:=False) Next With data .RowID = i .ModelYear = WksheetObj.Range(wkrng(0)).Value2 .VehMfcName = WksheetObj.Range(wkrng(1)).Value2 If WksheetObj.Range(wkrng(11)).Value2 = "Y" Then .EmgVeh = True Else .EmgVeh = False End If End With PartVehData.Add(data) Next Return PartVehData End Function End Module 

我正在尝试使用并行foreach和范围分区程序获取Excel工作表数据,在线程本地存储中创build列表,并最终使用线程安全方法(如synclock或读写器locking)添加它们

工作表中从第11行到最后一行的行将被读取并填充到列表(T)
当我执行上面的代码时,我遵守以下规则

  1. 当工作表中的行较大(例如> 2000)时,此代码每次都按预期工作
  2. 当工作表中的行较less时,此代码将在前几次迭代中返回部分列表(部分分区范围的数据丢失)。 如果我重复迭代它(按'a'键)多次,有时会返回预期的结果(最终列表计数=需要读取的Excel行数)

为什么观察到这种现象?
什么是使用并行foreach的解决scheme,如果我在第一次运行/迭代期间需要正确的结果,不pipe没有。 工作表中的行?