首先在Visual Studio2010新建了一个WinForm项目WinFormApp1,里面会默认有个叫Form1的窗口。假设,项目WinFormApp1的功能是为了查询远端Ftp服务器的文档目录,然后把查到的结果显示到Form1的界面上。通常的做法是在Form1.cs类中添加一个QueryFtpFiles()方法用于对远端的ftp服务器进行读操作,然后把读到的内容显示到界面上就算完成了。
在这个项目完成后,一般会先在本地或局域网内的某个Ftp服务器上先做个测试,这时你会发现程序很***地运行着。当你兴致冲冲地把代码交给你领导的时候,你的上司拿了远在美国的ftp服务器来试运行,点击“查询”按钮执行QueryFtpFiles()查询操作的时候,悲剧发生了——页面死掉了(没有响应)。。。你是不是觉得很没面子?有木有?
这里有个问题,就是在执行QueryFtpFiles()方法时,由于是对远端的ftp服务器进行读操作,本身IO操作就比较耗时,再考虑到网络延迟等因素,你的界面就不得不停下了等待读操作的完成。如果在这个读操作完成前,你急不可耐地点了下界面,就出现了“没有响应”的后果。
其实,我在运行这个项目的时候,实际上是在运行由这个项目自动在Debug或Release目录下生成的WinFormApp1.exe应用程序,而WinFormApp1.exe对于我的Windows Server2003即操作系统来说,他就是一个进程。
操作系统书中讲,传统的进程有两个基本属性:拥有资源的独立单位和可独立调度和分配的基本单位。由于在进程的创建、撤销和切换中,系统必须耗费较大的时空开销。引入线程后,传统的进程的两个基本属性分开,线程作为调度和分配的基本单位,进程作为独立分配资源的单位。也就是说,在完成一个复杂的功能时,可以在一个进程中建立多个线程,每个线程分别完成某一项简单功能,进程通过调度和排列组合这些线程来实现这个复杂的功能。
线程,其实就是一段代码,一个方法或一连串方法,这段代码或方法可以去完成某个功能,也可以什么都不用做,比如上面提到的QueryFtpFiles(),它其实就满足作为线程的基本条件。
再回到原来的“没有响应”的问题上,在执行WinFormApp1.exe这个进程的时候,这个进程会调用UI线程,其实也就是Form1.cs内的代码以及它调用的其他类的代码,因为QueryFtpFiles()也在Form1.cs这个类中,所以它也算是UI线程的一部分。WinFormApp1.exe进程执行时会首先调用这个UI线程(若没有定义其他线程,这时UI线程应该也是这个进程的唯一线程),这个UI线程在执行QueryFtpFile()方法的过程中由于耗时很多以至于这个进程其他什么什么操作都要停下来等待,包括你去点击界面的操作。
问题的描述应该就是这样了,至于解决方法,可以在UI线程中再定义另外一个线程thread1用来执行QueryFtpFile()方法就可以了。
原文链接:http://www.cnblogs.com/computer-lzy/archive/2011/07/19/2111002.html
【编辑推荐】