我必須處理大約170.000個文件,並且想要使用多個線程。 文件的名稱按照年份數格式連續,並按文件夾中的年份排序。 (但它們可以全部在同一個文件夾中)。 不同的年份有不同的文件數量。文件很小,只有幾個(每個文件大小爲< 20 KB)。在多個線程上打開多個文件
由於處理任務的輸出將存儲在SQL數據庫中,所以處理女巫的訂單是無關緊要的。 這將是什麼最好的方法?沒有兩次打開同一個文件?
我必須處理大約170.000個文件,並且想要使用多個線程。 文件的名稱按照年份數格式連續,並按文件夾中的年份排序。 (但它們可以全部在同一個文件夾中)。 不同的年份有不同的文件數量。文件很小,只有幾個(每個文件大小爲< 20 KB)。在多個線程上打開多個文件
由於處理任務的輸出將存儲在SQL數據庫中,所以處理女巫的訂單是無關緊要的。 這將是什麼最好的方法?沒有兩次打開同一個文件?
這裏是一個小例子:
public static class FilesProcessor
{
private static List<FileProcessor> m_FileProcessors;
public static void Start()
{
m_FileProcessors = new List<FileProcessor>();
for (Int32 year = 2005; year < DateTime.Now.Year; ++year)
InstanciateFileProcessor(year);
while (!FinishedLoading())
Application.DoEvents();
}
public static void Stop()
{
foreach (FileProcessor processor in m_FileProcessors)
processor.Stop()
m_FileProcessors.Clear();
m_FileProcessors = null;
}
private static Boolean FinishedLoading()
{
foreach (FileProcessor processor in m_FileProcessors)
{
if (processor.IsAlive() && !processor.FinishedLoading())
return false;
}
return true;
}
private static void InstanciateFileProcessor(Int32 year)
{
FileProcessor processor = new FileProcessor(year);
processor.Start();
m_FileProcessors.Add(processor);
}
}
然後FileProcessor類:
public sealed class FileProcessor
{
private Int32 m_Year;
public Boolean IsAlive()
{
return ((m_Thread != null) && m_Thread.IsAlive);
}
public Boolean FinishedLoading()
{
return ((m_Thread == null) || m_Thread.Join(10));
}
public FileProcessor(Int32 year)
{
m_Year = year;
m_Thread = new Thread(Load);
m_Thread.Name = "Background File Processor";
}
public void Start()
{
if (m_Thread != null)
m_Thread.Start();
}
public void Stop()
{
if ((m_Thread != null) && m_Thread.IsAlive)
m_Thread.Abort();
}
private void Load()
{
// Browse the Year folder...
// Get and read all fines one by one...
}
}
可能的解決方案之一是使用生產者/消費者設計模式。
您的製作人將獲得一個文件列表並提供一些ProducerConsumer
隊列。您的使用者將處理從隊列中取出的文件(或文件路徑)並對其進行處理(插入到數據庫中)。採用這種方法,每個文件只會被處理一次。
ProducerConsumer
隊列的問題描述在C# producer/consumer SO問題中。
編輯
但是,這項任務可能會變得複雜如
我會說1線程每年。 每個「年度線索」都會讀取以該年份號碼開頭的文件,並逐一讀取它們。 至於去到數據庫中,我會建議你要麼
另一種解決方案,將是線程,以產生插入語句到一個文件,然後執行該文件來執行插入,或者您可以使用批量插入工具。但是,這取決於表的結構,你的DBMS
我只有三年,從2010年開始到2012年結束,所以只有3個線程對我來說似乎很少...但是由於這是基於IO的,如果添加更多線程,我可能會遇到IO瓶頸...感謝幫助 – rukinhas
我可以在這裏看到兩種可能的方法。
首先,將問題分爲兩部分。 1 - 確定要處理的內容,2 - 處理。第1部分可能需要自行運行,因此您最終得到了需要處理的100%準確列表。然後你可以實現花哨的(或不是很花哨的)邏輯來分割列表和引入多個線程。
其次,做一些類似於@CarlosGrappa建議的東西。所以基本上你用自己的「預編程」過濾器創建每個線程。正如卡洛斯所說,這可能是今年。或者,您可以創建24個線程,每個文件時間戳一個小時。或者60個線程,每個線程都在一小時之後的某個特定分鐘內查看它基本上可以是任何給你一個明確的標準:(a)儘可能均勻地分割負載;(b)保證數據文件一次只處理一次。
很明顯,其中的第二種方法運行速度會更快,但您必須對如何分割文件進行一些額外的考慮。使用第一種方法,一旦獲得了完整列表,就可以基本上在處理器中一次性刪除100或1000或10000等文件,而不會過分關注如何執行這些文件。
使用.Net的並行類有什麼問題?
只是將一個集合傳遞給並行foreach循環。 .Net會爲您分配所有內容。您還可以傳入自定義分區程序,以便您可以使用塊分區。塊分區會導致線程繼續詢問更多任務。如果你不使用塊分區,所有的工作將被預先分配,從而當某些任務比其他任務花費更長時間(這可能導致某些線程處於空閒狀態,而一個線程仍有工作要做)時導致某些性能命中。
問題在哪裏? – lboshuizen
您沒有詢問。 – Servy
你有什麼試過?使用'Directory.GetFiles'獲取這些文件的列表,然後使用「parallel for」或任何你喜歡的東西來迭代。 – CodesInChaos