【问题标题】:Reading data from an excel file every 500 milliseconds in c#在c#中每500毫秒从excel文件中读取数据
【发布时间】:2016-07-04 09:15:05
【问题描述】:

我有一个 excel 文件,其中包含一些记录并且记录会在一秒钟内刷新。我想将所有记录存储在 SQL Server 数据库中。所以我的意图是每 500 毫秒后从这个文件中读取数据到我的数据库中。我已经成功地能够读取数据并存储在我的数据库中。但几分钟后,excel 挂起并处于无响应状态。

Excel._Application excel = (Excel._Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
clsDBOLiveData objDBOLiveData = new clsDBOLiveData();
clsDatabase objDatabase = new clsDatabase();

private static System.Timers.Timer aTimerLive_1;
private static System.Timers.Timer aTimerHist_1;
private static System.Timers.Timer aTimerLive_2;
private static System.Timers.Timer aTimerHist_2;


//Here I declare all variables.

public TradeData()
{
    SetTimer1_Data();
    SetTimer2_Data();
    SetTimerHist_1_Data();
    SetTimerHist_2_Data();
}


private void SetTimerLiveMCX_1_Data()
{
    aTimerLive_1 = new System.Timers.Timer(500);
    aTimerLive_1.Elapsed += OnTimedEvent_1;
    aTimerLive_1.AutoReset = true;
    aTimerLive_1.Enabled = true;
}

private void OnTimedEvent_1(Object source, ElapsedEventArgs e)
{
    try
    {
        Excel.Workbook workbook = excel.Workbooks[1];
        Excel.Worksheet workSheet = workbook.Worksheets.get_Item(1);
        Excel.Range range = workSheet.UsedRange;
        for (int j = 3; j < range.Rows.Count; j = j + 5)
        {
            if ((range.Cells[j, 2] as Excel.Range).Value2 == null || Convert.ToString((range.Cells[j, 2] as Excel.Range).Value2)=="")
                continue;
            clsDBOLiveData objDBOLiveData = new clsDBOLiveData();
            objDBOLiveData.SYMBOL_NAME = (string)(range.Cells[j, 8] as Excel.Range).Value2;
            objDBOLiveData.BAR_TIME= (double)(range.Cells[j, 2] as Excel.Range).Value2;
            objDBOLiveData.HIGH= (decimal)(range.Cells[j, 3] as Excel.Range).Value2;
            objDBOLiveData.LAST = (decimal)(range.Cells[j, 4] as Excel.Range).Value2;
            objDBOLiveData.LOW = (decimal)(range.Cells[j, 5] as Excel.Range).Value2;
            objDBOLiveData.OPEN = (decimal)(range.Cells[j, 6] as Excel.Range).Value2;
            objDBOLiveData.VOLUME = (decimal)(range.Cells[j, 7] as Excel.Range).Value2;
            objDBOLiveData.STATUS = (string)(range.Cells[j, 9] as Excel.Range).Value2;
            string strErrorMgs = "";
            if (!objDatabase.SaveData_1(objDBOLiveData, ref strErrorMgs)){}
        }
    }
    catch(Exception ex)
    {
    }
}

【问题讨论】:

标签: c# excel


【解决方案1】:

处理对象.. Excel 对象很重

【讨论】:

  • 重用对象不是比每 500 毫秒创建和处理一次更好吗?每次运行后只需重置数据完整性的值?
  • 不..!对此要非常小心。在您释放特定的 COM 对象之前,Excel 可能仍会锁定此 Excel 文件。打开 Excel,进行处理,然后释放 COM 对象,这一点很重要。不要让 COM 对象打开的时间超过需要的时间。我们(经常)在 Excel 2013 中遇到问题,因为 COM 对象没有被正确清理,所以隐藏的 EXCEL.EXE 实例正在运行。
  • 是的。我同意 Mike 的观点。excel 将锁定这些对象,并且可能会出错,因为无法更新文件,因为它被其他进程使用。
【解决方案2】:

天哪,这里有一些东西。

首先,正如其他读者所提到的。当您使用 Excel COM 对象时,您必须释放它们。

以下是我将如何设置您的代码样式:

Excel.Workbook workbook = null;
Excel.Worksheet workSheet = null;
Excel.Range range = null;
try
{
    workbook = excel.Workbooks[1];
    workSheet = workbook.Worksheets.get_Item(1);
    range = workSheet.UsedRange;
    . . . 
}
catch(Exception ex)
{
}
finally
{
    if (range != null)
        Marshal.FinalReleaseComObject(range);
    if (worksheet != null)
        Marshal.FinalReleaseComObject(worksheet);
    if (workbook != null)
        Marshal.FinalReleaseComObject(workbook);

    //  Garbage collection
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Default, false);
}

其次,我真的不相信在同一行中包含 Excel.Range 和 Value2 的任何行:

objDBOLiveData.SYMBOL_NAME = (string)(range.Cells[j, 8] as Excel.Range).Value2;

在 Google 上搜索“Excel COM 双点”,以获得(许多)关于为什么这是一个坏主意的解释。

就个人而言,如果您的所有数据都在一个工作表中,我建议将整个工作表读入object[,] 数组,然后遍历其中的值。

object[,] cellValues = (object[,])range.Value2;       

您也可以将此变量转换为 Array,如果这样可以更轻松地编写代码:

System.Array arr = (System.Array)cellValues;
int numOfRows = arr.GetUpperBound(0);
int numOfColumns = arr.GetUpperBound(1);

一次性读取所有单元格数据效率更高,COM 对象遗漏的机会更少。

最后一件事:小心UsedRange。

Excel.Range range = workSheet.UsedRange;

我们有一些示例,其中返回了巨大的范围(例如 16,000 列,而实际上只有 7 列数据),这反过来又使我们的代码在稍后崩溃,因为它试图迭代巨大的(空白)范围细胞。

阅读以下 StackOverflow 文章,了解查找电子表格中哪些单元格确实包含数据的唯一安全方法:

Alternative to UsedRange

呸。

【讨论】:

  • 现在它可以正常工作了。但最近我遇到了一个新问题。托管调试助手“RaceOnRCWCleanup”在“D:\TestPrograms\TestData\bin\Debug\TestData.vshost.exe”中检测到问题。附加信息:已尝试释放正在使用的 RCW。 RCW 正在活动线程或其他线程上使用。尝试释放正在使用的 RCW 可能会导致损坏或数据丢失。我无法解决这个问题。任何建议...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多