C#多线程和池
各位开发者好 我有一个关于在.NET(Framework 4.0)Windows服务上实现多线程的问题 基本上,服务应该执行以下操作:C#多线程和池,c#,multithreading,concurrency,C#,Multithreading,Concurrency,各位开发者好 我有一个关于在.NET(Framework 4.0)Windows服务上实现多线程的问题 基本上,服务应该执行以下操作: 扫描文件系统(特定目录)以查看是否有要处理的文件 如果有需要处理的文件,它应该使用线程池机制来发出预定数量的线程 每个线程将执行单个文件的上载操作 一个线程完成后,将再次扫描文件系统,以查看是否还有其他文件要处理(我希望避免让两个线程对同一个文件执行操作) 我正在努力寻找一种方法,让我只做最后一步 现在,我有一个函数,用于检索在主线程中运行的最大并发线程数:
- 扫描文件系统(特定目录)以查看是否有要处理的文件
- 如果有需要处理的文件,它应该使用线程池机制来发出预定数量的线程
- 每个线程将执行单个文件的上载操作
- 一个线程完成后,将再次扫描文件系统,以查看是否还有其他文件要处理(我希望避免让两个线程对同一个文件执行操作)
int maximumNumberOfConcurrentThreads = getMaxThreads(databaseConnection);
然后,仍然在主线程中,我有一个函数扫描目录并返回一个包含要处理的文件的列表
List<FileToUploadInfo> filesToUpload = getFilesToUploadFromFS(directory);
每个线程都应该调用以下函数(返回void):
现在,按照程序的结构,如果最大线程数设置为5,我将从列表中获取5个元素并上传它们。
一旦所有5个都完成了,我再抓取5个,然后做同样的事情,直到我没有任何剩余,如下面的代码所示
for (int index = 0; index < filesToUpload.Count; index = index + maximumNumberOfConcurrentThreads) {
try {
Parallel.For(0, maximumNumberOfConcurrentThreads, iteration => { if (index + iteration < filesToUpload .Count) { uploadFile(filesToUpload [index + iteration], databaseConnection, iteration); } });
}
catch (System.ArgumentOutOfRangeException outOfRange) {
debug("Exception in Parallel.For [" + outOfRange.Message + "]");
}
for(int index=0;index{if(index+iteration
但是,如果4个文件较小,每个文件的上载时间为5秒,而剩余的一个文件较大,需要30分钟,那么在4个文件上载后,我将只有一个文件上载,我需要等待它完成,然后才能开始上载列表中的其他文件
上传完列表中的所有文件后,我的服务进入睡眠状态,然后,当它再次醒来时,它再次扫描文件系统
什么策略最适合我的需要?走这条路线是明智的还是会造成并发性噩梦?我需要避免两次上载任何文件。首先,如果您实际上没有使用
System.Thread
s的功能,那么您可能想切换到System.Task
s。其次,如果4个小文件和1个大文件是常见的,那么这种策略并不可取(这里还有一个使用Task
s的原因;当您使用线程时,所有完成的“工作线程”很可能会被阻塞,直到组中最慢的线程完成,所以您有5个线程占用资源,但只有一个线程在工作)。第三,您可能希望重新创建设计,使其具有(例如,只是一个变体)N+1个工作循环,其中N个循环通过链“从列表获取文件=>处理它=>获取下一个文件…”一个是通过搜索磁盘上的差异来更新列表。是的,您需要在单例列表周围实现一些简单的同步,但这并不太难,也不会影响性能(您提到有一些数据库要连接,因此与网络通信时间相比,即使数百万次同步操作也可能毫无意义).哦,我的错,我看到你在使用TPL的并行。对于
,你已经在使用任务
s。那么,我的评论的第二部分是正确的-尝试一些worker循环,也许它可以更快。另外,请注意,并行。对于
并不能保证它会并行启动所有东西(这实际上很好,但无论如何,我想我应该提到它)。为了更好地确认它,可以将其他选项作为参数传递给它并进行设置(我不建议这样做)。这里有一个链接,显示在您尝试完成的相同过程中,我希望这会有所帮助。
uploadFile(fileToUpload, databaseConnection, currentThread);
for (int index = 0; index < filesToUpload.Count; index = index + maximumNumberOfConcurrentThreads) {
try {
Parallel.For(0, maximumNumberOfConcurrentThreads, iteration => { if (index + iteration < filesToUpload .Count) { uploadFile(filesToUpload [index + iteration], databaseConnection, iteration); } });
}
catch (System.ArgumentOutOfRangeException outOfRange) {
debug("Exception in Parallel.For [" + outOfRange.Message + "]");
}