2010-10-27 62 views
0

早上好,在C#中避免BinaryReader.ReadString()?

在應用程序啓動時,我正在寫我需要從文件讀取大約1,600,000項到Dictionary<Tuple<String, String>, Int32>。使用BinaryReader構建整個結構大約需要4-5秒(使用FileReader需要大約相同的時間)。我評測的代碼,發現這樣做在這個過程中最工作中的作用是BinaryReader.ReadString()。雖然這個過程只需要在啓動時運行一次,但我希望儘可能快地完成。有什麼方法可以避免BinaryReader.ReadString()並使此過程更快?

非常感謝。

+0

避免將'BinaryRe除非你真的需要它來讀取未對齊的位/數據,否則它們都會在一起。 – leppie 2010-10-27 09:47:37

回答

0

如果你認爲逐行讀取文件中的行是瓶頸,並且取決於其大小,你可以嘗試在一次閱讀這一切:

// read the entire file at once 
string entireFile = System.IO.File.ReadAllText(path); 

它並不能幫助,您可以嘗試使用信號量添加單獨的線程,該信號將在程序啓動時立即開始在後臺讀取,但在您嘗試訪問數據時阻止請求線程

這就是所謂的未來,你必須在喬恩斯基特的miscutil庫的實現。

// following line invokes "DoTheActualWork" method on a background thread. 
// DoTheActualWork returns an instance of MyData when it's done 
Future<MyData> calculation = new Future<MyData>(() => DoTheActualWork(path)); 

然後,一段時間後,你可以在主線程訪問值:

// following line blocks the calling thread until 
// the background thread completes 
MyData result = calculation.Value; 

如果你看一下

您在應用程序啓動時調用它Future's Value屬性,如果線程仍在運行,您可以看到它在AsyncWaitHandle處阻塞:

public TResult Value 
{ 
    get 
    { 
     if (!IsCompleted) 
     { 
      _asyncResult.AsyncWaitHandle.WaitOne(); 
      _lock.WaitOne(); 
     } 
     return _value; 
    } 
} 
5

你確定你絕對在繼續之前做到這一點?

我會檢查任務hiving開了一個單獨的線程結束後,即設置一個標誌的可能性。然後,您的啓動代碼只需啓動該線程並繼續其快捷方式,僅在以下兩種情況下暫停:

  • 該標誌尚未設置;和
  • 沒有更多的工作可以不用數據來完成。

通常情況下,速度的錯覺是不夠好,因爲人誰編寫了一個閃屏會告訴你。

如果您控制數據,另一種可能性是以更多的二進制形式存儲它,因此您可以用一次打擊(即,不解釋數據,只讀全部內容)將其全部打開。當然,這使得編輯應用程序之外的數據變得更加困難,但您並沒有將其作爲一項要求。

如果它的要求或者你不控制數據,我仍然看看我上面的第一個建議。

+0

+1,我討厭冷啓動應用程序。只有在絕對必要時才請求數據,或者在某些後臺任務中執行數據... – 2010-10-27 08:48:14

0

如果重複內的元組字符串,你可以重新組織你的文件,必須在一開始都不同,涉及的字符串,並且必須在文件的正文的字符串(整數)引用。您的主詞典不必更改,但在啓動期間需要使用所有不同的字符串(值)及其引用(鍵)的臨時詞典。