代码有时会完成,但并不总是给出相同的input

下面的程序在第一列中input带有产品ID的Excel文件(以MT或MU开头)。 然后,它将通过采购订单(PO)来查看由供应商提供的具有年份子文件夹的文件夹中的产品ID。 用户input文件夹path并指定要search的年份。 程序然后返回用户指定的原始电子表格中产品ID旁边列中最近的供应商,价格和date。 该计划需要大约3到4小时才能运行10,000个产品ID和数年的PO(数百个PO)。 有时会结束(有一个消息框显示完成后),有时它没有给出相同的确切input。 没有错误,但CPU使用率突然从大约40%到1%任何人都知道为什么?

string filepath = ""; string folderpath = ""; private void button1_Click(object sender, EventArgs e) { //New Excel App Excel._Application oApp = new Excel.Application(); oApp.Visible = true; //Opens Worksheet to be updated Excel.Workbook oWorkbook = oApp.Workbooks.Open(filepath); Excel.Worksheet oWorksheet = oWorkbook.Worksheets["Sheet1"]; //Takes all MT/MU numbers from first column of worksheet needing updating and puts them into a string Excel.Range firstColumn = oWorksheet.UsedRange.Columns[1]; System.Array myvalues = (System.Array)firstColumn.Cells.Value; string[] strArray = myvalues.OfType<object>().Select(o => o.ToString()).ToArray(); //Specify what year to begin and end looking at POs int beginYear = Convert.ToInt32(textBox2.Text); beginYear = int.Parse(textBox2.Text); int endYear = Convert.ToInt32(textBox3.Text); endYear = int.Parse(textBox3.Text); int count = 0; List<string> yearList = new List<string>(); while (count <= endYear-beginYear ) { int addYear = beginYear + count; string addYearString = addYear.ToString(); yearList.Add(addYearString); count++; } string[] years = yearList.ToArray(); foreach (string year in years) { //Creates array of all excel files existing in path (including subdirectories) in folder chosen by user IEnumerable<string> files = from f in Directory.GetFiles(folderpath, "*.xls", SearchOption.AllDirectories) where Path.GetDirectoryName(f).Contains(year) select f; foreach (string file in files) { //Opens file Excel._Application oApp2 = new Excel.Application(); oApp2.Visible = false; Excel.Workbook PO = oApp2.Workbooks.Open(file); Excel.Worksheet oWorksheet2 = PO.Worksheets["Sheet1"]; foreach (string item in strArray) { Excel.Range currentFind = null; string newestDateSoFar = "01/01/1900"; DateTime newestDateTimeSoFar = Convert.ToDateTime(newestDateSoFar); object misValue = System.Reflection.Missing.Value; Excel.Range xlRange = oWorksheet2.get_Range("C1"); //Looks through column for MT/MU number currentFind = xlRange.EntireColumn.Find(item, misValue, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext, true, misValue, misValue); //If there is a match in the PO if (currentFind != null) { //Get Date on PO string currentDate = null; DateTime currentDateTime = Convert.ToDateTime(currentDate); if (oWorksheet2.Cells[6, 6].Value != null) { currentDate = oWorksheet2.Cells[6, 6].Value.ToString(); currentDateTime = Convert.ToDateTime(currentDate); } Excel.Range xlRange2 = oWorksheet.get_Range("A1"); //Looks through column of worksheet needing updating for MT/MU number, so can compare date Excel.Range needsUpdatingFind = xlRange2.EntireColumn.Find(item, misValue, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByColumns, Excel.XlSearchDirection.xlNext, true, misValue, misValue); int dateColumn = Convert.ToInt32(textBox4.Text); dateColumn = int.Parse(textBox4.Text); if (needsUpdatingFind.get_Offset(0, dateColumn-1).Value != null) { newestDateSoFar = needsUpdatingFind.Offset[0, dateColumn-1].Value.ToString(); newestDateTimeSoFar = Convert.ToDateTime(newestDateSoFar); } //If Date on PO is most recent, get information that needs updating if (currentDateTime > newestDateTimeSoFar || needsUpdatingFind.get_Offset(0, dateColumn - 1).Value == null) { //Gets assosciated price and sets it in worksheet that needs updating string price = null; int priceColumn = Convert.ToInt32(textBox6.Text); priceColumn = int.Parse(textBox6.Text); if (currentFind.get_Offset(0, 2).Value != null) { price = currentFind.get_Offset(0, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } else if (currentFind.get_Offset(-1, 2).Value != null) { price = currentFind.get_Offset(-1, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } else if (currentFind.get_Offset(-2, 2).Value != null) { price = currentFind.get_Offset(-2, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } else if (currentFind.get_Offset(-3, 2).Value != null) { price = currentFind.get_Offset(-3, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } else if (currentFind.get_Offset(-4, 2).Value != null) { price = currentFind.get_Offset(-4, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } else if (currentFind.get_Offset(-5, 2).Value != null) { price = currentFind.get_Offset(-5, 2).Value.ToString(); needsUpdatingFind.Offset[0, priceColumn-1].Value = price; } //Gets assosciated supplier and sets it in worksheet that needs updating int supplierColumn = Convert.ToInt32(textBox5.Text); supplierColumn = int.Parse(textBox5.Text); string supplier = oWorksheet2.Cells[6, 2].Value.ToString(); needsUpdatingFind.Offset[0, supplierColumn-1].Value = supplier; //Gets assosciated PO date and sets it in worksheet that needs updating needsUpdatingFind.Offset[0, dateColumn-1].Value = currentDateTime.ToString(); //Resets current find currentFind = null; needsUpdatingFind = null; } while (Marshal.ReleaseComObject(xlRange2) != 0) { } xlRange2 = null; GC.Collect(); GC.WaitForPendingFinalizers(); } while (Marshal.ReleaseComObject(xlRange) != 0) { } xlRange = null; GC.Collect(); GC.WaitForPendingFinalizers(); } //Closes PO object missing = System.Reflection.Missing.Value; PO.Close(false, missing, missing); //Quits Excel oApp2.Quit(); //Manual disposal because of COM while (Marshal.ReleaseComObject(oApp2) != 0) { } while (Marshal.ReleaseComObject(PO) != 0) { } while (Marshal.ReleaseComObject(oWorksheet2) != 0) { } oApp2 = null; PO = null; oWorksheet2 = null; GC.Collect(); GC.WaitForPendingFinalizers(); } } MessageBox.Show("Done"); } private void button2_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); if (openFileDialog1.ShowDialog() == DialogResult.OK) { filepath = openFileDialog1.FileName; textBox1.Text = filepath; } } private void button3_Click(object sender, EventArgs e) { FolderBrowserDialog openFileDialog2 = new FolderBrowserDialog(); if (openFileDialog2.ShowDialog() == DialogResult.OK) { folderpath = openFileDialog2.SelectedPath; textBox7.Text = folderpath; } } } } 

您应该使用DataSetOleDbDataAdapter将数据放入内存,然后让C#/ Linq完成工作。 这听起来不像是在谈论太多的数据,所以看起来Interop是缓慢的根本原因。 下面是一个示例/比较: 打开Excel,parsing数据? 。 在这篇文章中,请注意ADO.Net和Interop之间的比较。 select的答案比替代的工作答案快得多。 看来你遇到了同样的问题。