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;

C#并行线程,但相互控制

优素福,你的"问题"很模糊。您可以采取一种方法,主线程下载文件,然后每次文件下载完成时,都会生成一个工作线程来解析该文件。这类事情有Task API或QueueUserWorkItem。我想你可能会以这种方式同时运行大量的工作线程,这不一定是更快完成工作的关键,而且可能会对计算机上的其他并发工作产生负面影响。

如果您想将其限制为两个线程,您可以考虑让下载线程在每次下载完成时将文件名写入队列。然后,您的解析器线程监视该队列(每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