欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容

admin 4个月前 (06-18) 科技 38 0

需求:遍历文件夹下的所有pdf文件,对每个pdf文件凭据二维码举行支解,再对支解后的文件的内容举行识别。

可以拆分为以下几个要害方式:

1.GetFileList方式:遍历文件,获取源文件动态数组(这里假设3个文件夹,每个文件夹下有3个文件,则源文件个数为9),耗时忽略不计

 1 static List<string> GetFileList(string strFilefolder)
 2         {
 3             List<string> list_file = new List<string>();
 4 
 5             for (int i = 0; i <= 2; i++)
 6             {
 7                 for (int j = 0; j <= 2; j++)
 8                     list_file.Add("File" + i + j);
 9             }
10 
11             return list_file;
12         }
View Code

2.SplitProcess方式:支解原始pdf文件,识别二维码(假设耗时500ms),将一个pdf文件支解为N(这里假设个数为6)个子文件

 1 static void SplitProcess(string sourcefile)
 2         {
 3             Console.WriteLine("SplitFile Start:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));            
 4             for (int i = 0; i <= 5; i++)
 5             {
 6                 //模拟支解单个文件的历程,破费500ms
 7                 Thread.Sleep(500);
 8                 string split_file = sourcefile + i;
 9                 Console.WriteLine("file ready:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
10                 RecognizeProcess(split_file);
11             }
12             Console.WriteLine("SplitFile Completed:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));            
13         }
View Code

3.RecognizeProcess方式:识别子文件的内容:加载识别库,设置识别参数,截取识别区域图像,图像处置(如缩放,降噪,灰度转换等),识别(假设耗时5000ms

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第2张
1 static void RecognizeProcess(string split_file)
2         {
3             //模拟识别的历程,破费5000ms
4             Thread.Sleep(5000);
5             Console.WriteLine("ocrFile Completed:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
6         }
View Code

单线程处置:

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第2张
 1 static void Main(string[] args)
 2         {
 3             Console.WriteLine("Enter Main" + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
 4             string strFilefolder = "";
 5             OcrProcess(strFilefolder);
 6             Console.WriteLine("Main Completed" + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
 7             Console.ReadKey();
 8         }
 9 
10         static void OcrProcess(string strFilefolder)
11         {            
12             List<string> list_sourcefile = GetFileList(strFilefolder);
13             list_sourcefile.ForEach((sourcefile) =>
14             {
15                 Console.WriteLine(sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
16                 //这里对文件举行支解
17                 SplitProcess(sourcefile);
18             });            
19         }
View Code

这个单线程处置的执行效果我们可以预估以下,应该大于 9 * 6 * (0.5 + 5) = 297 秒。

现实效果:

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第6张

 …… 

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第7张

 最先时间 2020-06-17 15:22:28 6104 竣事时间 2020-06-17 15:27:26 1541 

由于是线性处置,整个历程花费的时间约5分钟,以是必须要举行优化,以是思量用多线程来提高效率。

优化偏向:

1.多线程,使用Task并行对源文件举行支解 

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第2张
 1 static void OcrProcess(string strFilefolder)
 2         {
 3             List<Task> tasks = new List<Task>();  
 4             List<string> list_sourcefile = GetFileList(strFilefolder);
 5             list_sourcefile.ForEach((sourcefile) =>
 6             {
 7                 Task task = Task.Factory.StartNew( () =>
 8                 { 
 9                     Console.WriteLine(sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
10                     //这里对文件举行支解
11                     SplitProcess(sourcefile);
12                 });
13                 tasks.Add(task);                
14             });
15             Task.WaitAll(tasks.ToArray());
16         }
View Code

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第10张

 ……

 欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第11张

最先时间 2020-06-17 15:51:54 5458 竣事时间 2020-06-17 15:52:35 3144 

整个历程花费的时间约41秒,优化效果显著。

2.每支解出来一个文件,开启子线程,举行识别

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第2张
 1 static void SplitProcess(string sourcefile)
 2         {
 3             List<Task> tasks = new List<Task>();
 4             Console.WriteLine("SplitFile Start:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));            
 5             for (int i = 0; i <= 5; i++)
 6             {
 7                 //模拟支解单个文件的历程,破费500ms
 8                 Thread.Sleep(500);
 9                 string split_file = sourcefile + i;
10                 Console.WriteLine("file ready:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
11                 Task task = Task.Factory.StartNew(() =>
12                 {
13                     RecognizeProcess(split_file);
14                 });
15                 tasks.Add(task);
16             }
17             Task.WaitAll(tasks.ToArray());
18             Console.WriteLine("SplitFile Completed:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));            
19         }
View Code

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第14张

  ……

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第15张

 最先时间 2020-06-17 15:58:59 2591 竣事时间 2020-06-17 15:59:28 9051 

整个历程花费的时间约29秒,运行时间进一步缩短。 

然而,最后再思索一下,如果把多线程发挥到极致,理想状态应该是多少秒执行完毕?

500ms:第一个文件被支解出来,在这个时间里,线程同步的话,那么后续文件也一并被支解出来了。

5500ms:第一个支解文件已识别,在这个时间里,线程同步的话,后续文件应该也一并都被识别出来了。

以是,理想情况下,应该是5.5秒,而与29秒差距太大了,应该另有优化空间!

3.怎么优化?向什么偏向优化?我们不妨不用Task,回归到Thread自己来试试。

可是Thread运行时没有Task.WaitAll()这样的控制方式,因此,我们还要引入WaitHandle和ManualResetEvent来举行多线程治理。

 

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第2张
 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("Enter Main" + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
 6             string strFilefolder = "";
 7             OcrProcess(strFilefolder);
 8             Console.WriteLine("Main Completed" + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
 9             Console.ReadKey();
10         }        
11 
12         static void OcrProcess(string strFilefolder)
13         {            
14             List<ManualResetEvent> split_waits = new List<ManualResetEvent>();
15             List<string> list_sourcefile = GetFileList(strFilefolder);
16             list_sourcefile.ForEach((sourcefile) =>
17             {
18                 Thread m_thread = new Thread(() =>
19                 {
20                     ManualResetEvent mre = new ManualResetEvent(false);
21                     split_waits.Add(mre);
22                     Console.WriteLine(sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
23                     //这里对文件举行支解
24                     SplitProcess(sourcefile);
25                     mre.Set();
26                 });
27                 m_thread.Start();
28             });
29             WaitHandle.WaitAll(split_waits.ToArray());
30         }
31 
32         static void SplitProcess(string sourcefile)
33         {
34             Console.WriteLine("SplitFile Start:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
35             var ocr_waits = new List<EventWaitHandle>();
36             for (int i = 0; i <= 5; i++)
37             {
38                 //模拟支解单个文件的历程,破费500ms
39                 Thread.Sleep(500);
40                 string split_file = sourcefile + i;
41                 Console.WriteLine("file ready:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
42                 ManualResetEvent mre_child = new ManualResetEvent(false);
43                 ocr_waits.Add(mre_child);
44                 Thread m_child_thread = new Thread(() =>
45                 {
46                     Console.WriteLine("m_child_thread enter:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
47                     RecognizeProcess(split_file);                    
48                     mre_child.Set();
49                     Console.WriteLine("m_child_thread after set:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
50                 });
51                 m_child_thread.Start();
52             }
53             WaitHandle.WaitAll(ocr_waits.ToArray());
54             Console.WriteLine("SplitFile Completed:" + sourcefile + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));            
55         }
56 
57         static void RecognizeProcess(string split_file)
58         {
59             //模拟识别的历程,破费5000ms
60             Thread.Sleep(5000);
61             Console.WriteLine("ocrFile Completed:" + split_file + DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss ffff"));
62         }
63 
64         static List<string> GetFileList(string strFilefolder)
65         {
66             List<string> list_file = new List<string>();
67             for (int i = 0; i <= 2; i++)
68             {
69                 for (int j = 0; j <= 2; j++)
70                     list_file.Add("File" + i + j);
71             }
72             return list_file;
73         }
74     }
View Code

 

 欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第18张

  ……

欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容 第19张

 最先时间 2020-06-17 15:28:17 2397 竣事时间 2020-06-17 16:28:27 9151 

整个历程花费的时间约10秒,运行时间与理论的5.5秒已经十分靠近(由于Thread切换上下文,Console.WriteLine都有一定的耗时),可以说目的已经杀青。 

Tips:

ManualResetEvent初始状态为false示意不将线程信号量初始值置为signal,线程会自动往下执行,执行Set()方式时,将线程信号量置为signal。

WaitHandle.WaitAll(split_waithandle1,split_waithandle2); //一直守候,直到split_waithandle1,split_waithandle2信号量均被置为signal才会往下执行。

不足之处:

开启Thread要受到系统的限制,以是本例线程数必须思量操作系统线程最大值限制。

 

,

欧博亚洲官网开户网址

欢迎进入欧博亚洲官网开户网址(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:欧博亚洲官网开户网址:多线程实例——遍历文件夹支解文件识别文件内容

网友评论

  • (*)

最新评论

最近发表

文章归档

站点信息

  • 文章总数:653
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1043
  • 评论总数:252
  • 浏览总数:8137