2014-10-26 35 views
-2

我想寫一個將有2個線程的程序。一會下載另一個會解析下載的文件。棘手的部分是我不能同時使用2個解析線程,因爲它使用庫技術來解析文件。請幫助一個建議。謝謝。C#並行線程但彼此控制

Foreach(string filename in filenames) 
{ 
    //start downloading thread here; 
    readytoparse.Add(filename); 
} 

Foreach(string filename in readytoparse) 
{ 
    //start parsing here 
} 

我結束了以下邏輯

bool parserrunning = false; 
List<string> readytoparse = new List<string>(); 
List<string> filenames= new List<string>(); 

//downloading method 
Foreach(string filename in filenames) 
{ 
    //start downloading thread here; 
    readytoparse.Add(filename); 
    if(parserrunning == false; 
    { 
     // start parser method 
    } 
} 

//parsing method 
parserrunning = true; 
list<string> _readytoparse = new List<string>(readytoparse); 
Foreach(string filename in _readytoparse) 
{ 

    //start parsing here 
} 
parserrunning = false; 
+1

是否有你需要使用兩個單獨的線程的原因?如果您將工作細分爲多個非UI線程,似乎您認爲該任務將更快完成,而這不一定是最好的邏輯。 爲什麼不使用單個非UI線程,並讓該線程完成所有下載,然後進行所有解析? – furkle 2014-10-26 16:12:35

+1

你需要一個基本的並行性教程。許多方法都是可能的,所有這些方法都已被多次覆蓋。 – usr 2014-10-26 16:14:03

+0

我已經完成了該代碼。該代碼很慢。它需要5個小時。我想盡量減少它 – 2014-10-26 16:14:27

回答

0

優素福,你的 「問題」 是非常模糊的。您可以採取一種方法,讓主線程下載文件,然後每次文件完成下載時,都會生成一個工作線程來解析該文件。有這種事情的任務API或QueueUserWorkItem。我想可能最終會出現大量以這種方式併發運行的工作線程,這不一定是讓工作更快完成並可能對計算機上其他併發工作產生負面影響的關鍵。

如果您想將其限制爲兩個線程,則可以考慮讓下載線程在每次下載完成時將文件名寫入隊列。然後,解析器線程監視該隊列(每隔x秒喚醒一次,檢查隊列以查看是否有任何要執行的操作,執行該操作,再次檢查隊列,如果沒有任何操作,則返回睡眠x秒,重複) 。

如果您希望解析器具有永續性,請使該隊列持久化(數據庫,MSMQ,磁盤上正在運行的文本文件 - ,某種東西持續存在)。這樣,如果發生中斷(計算機崩潰,程序崩潰,斷電),解析器可以從停止的地方開始。

代碼同步的意義在於,你顯然不能讓解析器解析下載器仍在下載的文件,並且如果你有兩個線程使用隊列,那麼顯然你必須保護那個隊列併發訪問。

無論您使用監視器還是互斥鎖,還是QueueUserWorkItem或Task API都是有學問的。在.NET框架中有很多支持來同步和並行處理工作單元。

0

我建議避免所有的心疼,自己做任何主動性,並使用專爲這種事情設計的圖書館。

我推薦微軟的Reactive Framework(Rx)。

下面的代碼:

var query = 
    from filename in filenames.ToObservable(Scheduler.Default) 
    from file in Observable.Start(() => /* read file */, Scheduler.Default) 
    from parsed in Observable.Start(() => /* parse file */, Scheduler.Default) 
    select new 
    { 
     filename, 
     parsed, 
    }; 

query.Subscribe(fp => 
{ 
    /* Do something with finished file */ 
}); 

很簡單。

如果您解析圖書館僅僅是單線程的,則加入這一行:

var els = new EventLoopScheduler(); 

然後用els上解析線替換Scheduler.Default