2014-10-26 75 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