C#并行线程,但相互控制
本文关键字:控制 并行 线程 | 更新日期: 2023-09-27 18:27:50
我想写一个有两个线程的程序。一个将下载另一个将解析下载的文件。棘手的部分是,我不能同时有两个解析线程,因为它使用库技术来解析文件。请帮忙提个建议。非常感谢。
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;
如果您想将其限制为两个线程,您可以考虑让下载线程在每次下载完成时将文件名写入队列。然后,您的解析器线程监视该队列(每x秒唤醒一次,检查队列以查看是否有什么要做,完成工作,再次检查队列,如果没有什么要做的,返回睡眠x秒,重复)。
如果您希望解析器具有弹性,请使该队列持久化(数据库、MSMQ、磁盘上运行的文本文件--something持久化)。这样,如果出现中断(计算机崩溃、程序崩溃、断电),解析器可以从中断的地方重新启动
代码同步的作用是,你显然不能让解析器试图解析下载者仍在下载的文件,如果你有两个线程使用一个队列,那么你显然必须保护该队列免受并发访问。
无论您使用监视器还是Mutexes,或者QueueUserWorkItem还是Task API都是学术性的。在.NET框架中有很多对同步和并行化工作单元的支持。
我建议自己用任何素数做这件事时避免所有的心痛,并使用为这类事情设计的库。
我推荐微软的反应式框架(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();
然后在解析行上将Scheduler.Default
替换为els
。