2016-07-04 32 views
0

私はいくつかのレコードを含むExcelファイルを持っていて、1秒以内にそのリフレッシュを記録します。すべてのレコードをSQL Serverデータベースに保存したい。だから私の意図は、500ミリ秒ごとにこのファイルから私のデータベースにデータを読み込むことです。私は正常にデータを読んで私のデータベースに保存することができました。しかし、数分後、応答が遅くなり応答しない状態になります。Cで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) 
    { 
    } 
} 
+0

このサンプルのように、リリースまたは廃棄してください。http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects –

+0

ヒントは一切役立ちましたか? –

答えて

0

ああまあ重いです。

最初に、他の読者が述べたとおりです。 Excel COMオブジェクトを使用している場合、をリリースする必要があります。

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

がためにGoogle検索を実行します。

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.RangeValue2を含む任意の行を信頼しないでしょう。ここ

は、私はあなたのコードのスタイルを設定する方法をですなぜこれが悪い考えであるかについての(多くの)説明のための "Excel COM double dot"。

個人的に、すべてのデータが1つのワークシートにある場合は、ワークシート全体をobject[,]アレイに読み込んでそこの値をループすることをお勧めします。 COMの少ないチャンスで、より効率的で一度にセルデータのすべてを読ん

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

:それはあなたのコードのために、それが容易になり場合

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

またArrayにこの変数を変換することができますオブジェクトが残っています。

最後の一つです:UsedRangeに注意してください。今度は、後で私たちのコードをクラッシュし、(データの唯一の実際に7列がありますとき、例えば16,000列)、それは巨大なを反復処理しようとしたとして

Excel.Range range = workSheet.UsedRange; 

私たちは、これは巨大な範囲を返した例がありました(ブランク)範囲の細胞。

Alternative to UsedRange

ふう:

は、スプレッドシート内のセルが実際にデータが含まれていませんどの見つけるための唯一の安全な方法を記述するために、次のStackOverflowの記事の読み取りを持っています。

+0

今、それはうまくいきます。しかし、最近私は新しい問題に直面しました。 管理されたデバッグアシスタント 'RaceOnRCWCleanup'が 'D:\ TestPrograms \ TestData \ bin \ Debug \ TestData.vshost.exe'の問題を検出しました。 追加情報:使用中のRCWを解放しようとしました。 RCWは、アクティブなスレッドまたは別のスレッドで使用されています。使用中のRCWを解放しようとすると、破損やデータの消失を引き起こす可能性があります。 私はこの問題を解決できません。何か提案... –

1

オブジェクトを廃棄.. Excelオブジェクトは、ここでいくつかのこと

+0

オブジェクトを再利用することは、500msごとに作成して廃棄するほうがよいでしょうか?毎回実行した後、データの整合性の値をリセットするだけですか? – Mfusiki

+0

No ..!これには非常に注意してください。特定のCOMオブジェクトを解放するまで、ExcelはこのExcelファイルをロックしたままにしておくことがあります。 Excelを開いて処理し、COMオブジェクトを解放することが重要です。 COMオブジェクトを必要以上に長く開いたままにしないでください。COMオブジェクトが正しくクリーンアップされていないため、Excel 2013でEXCEL.EXEの隠しインスタンスを実行しているときに問題が発生することがよくありました(多くの場合)。 –

+0

はい..私はMikeに同意します。excelはこれらのオブジェクトをロックし、別のプロセスで使用されているのでファイルを更新できないためエラーが発生する可能性があります。 –

関連する問題