﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-302班</title><link>http://www.blogjava.net/yank/</link><description>java突击队</description><language>zh-cn</language><lastBuildDate>Mon, 18 May 2026 22:27:40 GMT</lastBuildDate><pubDate>Mon, 18 May 2026 22:27:40 GMT</pubDate><ttl>60</ttl><item><title>新的博客地址，希望大家能够继续支持！</title><link>http://www.blogjava.net/yank/archive/2008/03/26/188777.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Wed, 26 Mar 2008 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2008/03/26/188777.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/188777.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2008/03/26/188777.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/188777.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/188777.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: <a href="http://yank.cnblogs.com/">新的博客地址cnblogs,希望大家能够继续支持！</a>&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2008/03/26/188777.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/188777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2008-03-26 16:17 <a href="http://www.blogjava.net/yank/archive/2008/03/26/188777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析.Net下的多线程编程</title><link>http://www.blogjava.net/yank/archive/2007/09/27/148886.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Thu, 27 Sep 2007 13:10:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/09/27/148886.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/148886.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/09/27/148886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/148886.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/148886.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 多线程是许多操作系统所具有的特性，它能大大提高程序的运行效率，所以多线程编程技术为编程者广泛关注。目前微软的.Net战略正进一步推进，各种相关的技术正为广大编程者所接受，同样在.Net中多线程编程技术具有相当重要的地位。本文我就向大家介绍在.Net下进行多线程编程的基本方法和步骤。&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/09/27/148886.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/148886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-09-27 21:10 <a href="http://www.blogjava.net/yank/archive/2007/09/27/148886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析.Net下的多线程编程</title><link>http://www.blogjava.net/yank/archive/2007/09/27/148884.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Thu, 27 Sep 2007 13:09:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/09/27/148884.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/148884.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/09/27/148884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/148884.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/148884.html</trackback:ping><description><![CDATA[多线程是许多操作系统所具有的特性，它能大大提高程序的运行效率，所以多线程编程技术为编程者广泛关注。目前微软的.Net战略正进一步推进，各种相关的技术正为广大编程者所接受，同样在.Net中多线程编程技术具有相当重要的地位。本文我就向大家介绍在.Net下进行多线程编程的基本方法和步骤。&nbsp; <br />
<br />
&nbsp;&nbsp;开始新线程&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;在.Net下创建一个新线程是非常容易的，你可以通过以下的语句来开始一个新的线程：&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Thread&nbsp;thread&nbsp;=&nbsp;new&nbsp;Thread&nbsp;(new&nbsp;ThreadStart&nbsp;(ThreadFunc));&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.Start&nbsp;();&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;第一条语句创建一个新的Thread对象，并指明了一个该线程的方法。当新的线程开始时，该方法也就被调用执行了。该线程对象通过一个System..Threading.ThreadStart类的一个实例以类型安全的方法来调用它要调用的线程方法。&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;第二条语句正式开始该新线程，一旦方法Start（）被调用，该线程就保持在一个"alive"的状态下了，你可以通过读取它的IsAlive属性来判断它是否处于"alive"状态。下面的语句显示了如果一个线程处于"alive"状态下就将该线程挂起的方法：&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;if&nbsp;(thread.IsAlive)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.Suspend&nbsp;();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
<br />
&nbsp;&nbsp;不过请注意，线程对象的Start（）方法只是启动了该线程，而并不保证其线程方法ThreadFunc（）能立即得到执行。它只是保证该线程对象能被分配到CPU时间，而实际的执行还要由操作系统根据处理器时间来决定。&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;一个线程的方法不包含任何参数，同时也不返回任何值。它的命名规则和一般函数的命名规则相同。它既可以是静态的（static）也可以是非静态的（nonstatic）。当它执行完毕后，相应的线程也就结束了，其线程对象的IsAlive属性也就被置为false了。下面是一个线程方法的实例：&nbsp; <br />
<br />
&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;ThreadFunc()&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;10;&nbsp;i++)&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Console.WriteLine("ThreadFunc&nbsp;{0}",&nbsp;i);&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;前台线程和后台线程&nbsp; <br />
<br />
&nbsp;&nbsp;.Net的公用语言运行时（Common&nbsp;Language&nbsp;Runtime，CLR）能区分两种不同类型的线程：前台线程和后台线程。这两者的区别就是：应用程序必须运行完所有的前台线程才可以退出；而对于后台线程，应用程序则可以不考虑其是否已经运行完毕而直接退出，所有的后台线程在应用程序退出时都会自动结束。&nbsp; <br />
<br />
&nbsp;&nbsp;一个线程是前台线程还是后台线程可由它的IsBackground属性来决定。这个属性是可读又可写的。它的默认值为false，即意味着一个线程默认为前台线程。我们可以将它的IsBackground属性设置为true，从而使之成为一个后台线程。&nbsp; <br />
<br />
&nbsp;&nbsp;下面的例子是一个控制台程序，程序一开始便启动了10个线程，每个线程运行5秒钟时间。由于线程的IsBackground属性默认为false，即它们都是前台线程，所以尽管程序的主线程很快就运行结束了，但程序要到所有已启动的线程都运行完毕才会结束。示例代码如下：&nbsp; <br />
<br />
&nbsp;&nbsp;using&nbsp;System;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;using&nbsp;System.Threading;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;class&nbsp;MyApp&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;Main&nbsp;()&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;for&nbsp;(int&nbsp;i=0;&nbsp;i&lt;10;&nbsp;i++)&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Thread&nbsp;thread&nbsp;=&nbsp;new&nbsp;Thread&nbsp;(new&nbsp;ThreadStart&nbsp;(ThreadFunc));&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.Start&nbsp;();&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;private&nbsp;static&nbsp;void&nbsp;ThreadFunc&nbsp;()&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;DateTime&nbsp;start&nbsp;=&nbsp;DateTime.Now;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;while&nbsp;((DateTime.Now&nbsp;-&nbsp;start).Seconds&nbsp;&lt;5)&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp;<br />
<br />
接下来我们对上面的代码进行略微修改，将每个线程的IsBackground属性都设置为true，则每个线程都是后台线程了。那么只要程序的主线程结束了，整个程序也就结束了。示例代码如下：&nbsp; <br />
&nbsp;&nbsp;using&nbsp;System;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;using&nbsp;System.Threading;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;class&nbsp;MyApp&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;Main&nbsp;()&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;for&nbsp;(int&nbsp;i=0;&nbsp;i&lt;10;&nbsp;i++)&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Thread&nbsp;thread&nbsp;=&nbsp;new&nbsp;Thread&nbsp;(new&nbsp;ThreadStart&nbsp;(ThreadFunc));&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.IsBackground&nbsp;=&nbsp;true;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.Start&nbsp;();&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;private&nbsp;static&nbsp;void&nbsp;ThreadFunc&nbsp;()&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;DateTime&nbsp;start&nbsp;=&nbsp;DateTime.Now;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;while&nbsp;((DateTime.Now&nbsp;-&nbsp;start).Seconds&nbsp;&lt;5)&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
<br />
&nbsp;&nbsp;既然前台线程和后台线程有这种差别，那么我们怎么知道该如何设置一个线程的IsBackground属性呢？下面是一些基本的原则：对于一些在后台运行的线程，当程序结束时这些线程没有必要继续运行了，那么这些线程就应该设置为后台线程。比如一个程序启动了一个进行大量运算的线程，可是只要程序一旦结束，那个线程就失去了继续存在的意义，那么那个线程就该是作为后台线程的。而对于一些服务于用户界面的线程往往是要设置为前台线程的，因为即使程序的主线程结束了，其他的用户界面的线程很可能要继续存在来显示相关的信息，所以不能立即终止它们。这里我只是给出了一些原则，具体到实际的运用往往需要编程者的进一步仔细斟酌。&nbsp; <br />
<br />
&nbsp;&nbsp;线程优先级&nbsp; <br />
<br />
&nbsp;&nbsp;一旦一个线程开始运行，线程调度程序就可以控制其所获得的CPU时间。如果一个托管的应用程序运行在Windows机器上，则线程调度程序是由Windows所提供的。在其他的平台上，线程调度程序可能是操作系统的一部分，也自然可能是.Net框架的一部分。不过我们这里不必考虑线程的调度程序是如何产生的，我们只要知道通过设置线程的优先级我们就可以使该线程获得不同的CPU时间。&nbsp; <br />
<br />
&nbsp;&nbsp;线程的优先级是由Thread.Priority属性控制的，其值包含：ThreadPriority.Highest、ThreadPriority.AboveNormal、ThreadPriority.Normal、ThreadPriority.BelowNormal和ThreadPriority.Lowest。从它们的名称上我们自然可以知道它们的优先程度，所以这里就不多作介绍了。&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;线程的默认优先级为ThreadPriority.Normal。理论上，具有相同优先级的线程会获得相同的CPU时间，不过在实际执行时，消息队列中的线程阻塞或是操作系统的优先级的提高等原因会导致具有相同优先级的线程会获得不同的CPU时间。不过从总体上来考虑仍可以忽略这种差异。你可以通过以下的方法来改变一个线程的优先级。&nbsp; <br />
<br />
&nbsp;&nbsp;thread.Priority&nbsp;=&nbsp;ThreadPriority.AboveNormal;&nbsp; <br />
<br />
&nbsp;&nbsp;或是：&nbsp; <br />
<br />
&nbsp;&nbsp;thread.Priority&nbsp;=&nbsp;ThreadPriority.BelowNormal;&nbsp; <br />
<br />
&nbsp;&nbsp;通过上面的第一句语句你可以提高一个线程的优先级，那么该线程就会相应的获得更多的CPU时间；通过第二句语句你便降低了那个线程的优先级，于是它就会被分配到比原来少的CPU时间了。你可以在一个线程开始运行前或是在它的运行过程中的任何时候改变它的优先级。理论上你还可以任意的设置每个线程的优先级，不过一个优先级过高的线程往往会影响到其他线程的运行，甚至影响到其他程序的运行，所以最好不要随意的设置线程的优先级。&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;挂起线程和重新开始线程&nbsp; <br />
<br />
&nbsp;&nbsp;Thread类分别提供了两个方法来挂起线程和重新开始线程，也就是Thread.Suspend能暂停一个正在运行的线程，而Thread.Resume又能让那个线程继续运行。不像Windows内核，.Net框架是不记录线程的挂起次数的，所以不管你挂起线程过几次，只要一次调用Thread.Resume就可以让挂起的线程重新开始运行。&nbsp; <br />
<br />
&nbsp;&nbsp;Thread类还提供了一个静态的Thread.Sleep方法，它能使一个线程自动的挂起一定的时间，然后自动的重新开始。一个线程能在它自身内部调用Thread.Sleep方法，也能在自身内部调用Thread.Suspend方法，可是一定要别的线程来调用它的Thread.Resume方法才可以重新开始。这一点是不是很容易想通的啊？下面的例子显示了如何运用Thread.Sleep方法：&nbsp; <br />
<br />
&nbsp;&nbsp;while&nbsp;(ContinueDrawing)&nbsp;{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;DrawNextSlide&nbsp;();&nbsp;&nbsp; <br />
&nbsp;&nbsp;Thread.Sleep&nbsp;(5000);&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
<br />
&nbsp;&nbsp;终止线程&nbsp; <br />
&nbsp;&nbsp;&nbsp;在托管的代码中，你可以通过以下的语句在一个线程中将另一个线程终止掉：&nbsp; <br />
&nbsp;&nbsp;thread.Abort&nbsp;();&nbsp; <br />
&nbsp;&nbsp;下面我们来解释一下Abort（）方法是如何工作的。因为公用语言运行时管理了所有的托管的线程，同样它能在每个线程内抛出异常。Abort（）方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort（）方法被调用后，目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话，该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话，该目标线程就根本不会终止。不过这种情况只是一些特例，更多的情况是目标线程在调用托管的代码，一旦Abort（）被调用那么该线程就立即终止了。&nbsp; <br />
<br />
&nbsp;&nbsp;在实际应用中，一个线程终止了另一个线程，不过往往要等那个线程完全终止了它才可以继续运行，这样的话我们就应该用到它的Join（）方法。示例代码如下：&nbsp; <br />
<br />
&nbsp;&nbsp;thread.Abort&nbsp;();&nbsp;//&nbsp;要求终止另一个线程&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;thread.Join&nbsp;();&nbsp;//&nbsp;只到另一个线程完全终止了，它才继续运行&nbsp; <br />
<br />
&nbsp;&nbsp;但是如果另一个线程一直不能终止的话（原因如前所述），我们就需要给Join（）方法设置一个时间限制，方法如下：&nbsp; <br />
<br />
&nbsp;&nbsp;thread.Join&nbsp;(5000);&nbsp;//&nbsp;暂停5秒&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;这样，在5秒后，不管那个线程有没有完全终止，本线程就强行运行了。该方法还返回一个布尔型的值，如果是true则表明那个线程已经完全终止了，而如果是false的话，则表明已经超过了时间限制了。&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;时钟线程&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;.Net框架中的Timer类可以让你使用时钟线程，它是包含在System.Threading名字空间中的，它的作用就是在一定的时间间隔后调用一个线程的方法。下面我给大家展示一个具体的实例，该实例以1秒为时间间隔，在控制台中输出不同的字符串，代码如下：&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;using&nbsp;System;&nbsp;&nbsp; <br />
&nbsp;&nbsp;using&nbsp;System.Threading;&nbsp;&nbsp; <br />
&nbsp;&nbsp;class&nbsp;MyApp&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp; <br />
&nbsp;&nbsp;private&nbsp;static&nbsp;bool&nbsp;TickNext&nbsp;=&nbsp;true;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;Main&nbsp;()&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp;&nbsp; <br />
&nbsp;&nbsp;Console.WriteLine&nbsp;("Press&nbsp;Enter&nbsp;to&nbsp;terminate...");&nbsp;&nbsp; <br />
&nbsp;&nbsp;TimerCallback&nbsp;callback&nbsp;=&nbsp;new&nbsp;TimerCallback&nbsp;(TickTock);&nbsp;&nbsp; <br />
&nbsp;&nbsp;Timer&nbsp;timer&nbsp;=&nbsp;new&nbsp;Timer&nbsp;(callback,&nbsp;null,&nbsp;1000,&nbsp;1000);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Console.ReadLine&nbsp;();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;private&nbsp;static&nbsp;void&nbsp;TickTock&nbsp;(object&nbsp;state)&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;Console.WriteLine&nbsp;(TickNext&nbsp;?&nbsp;"Tick"&nbsp;:&nbsp;"Tock");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;TickNext&nbsp;=&nbsp;!&nbsp;TickNext;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp;&nbsp; <br />
&nbsp;&nbsp;从上面的代码中，我们知道第一个函数回调是在1000毫秒后才发生的，以后的函数回调也是在每隔1000毫秒之后发生的，这是由Timer对象的构造函数中的第三个参数所决定的。程序会在1000毫秒的时间间隔后不断的产生新线程，只到用户输入回车才结束运行。不过值得注意的是，虽然我们设置了时间间隔为1000毫秒，但是实际运行的时候往往并不能非常精确。因为Windows操作系统并不是一个实时系统，而公用语言运行时也不是实时的，所以由于线程调度的千变万化，实际的运行效果往往是不能精确到毫秒级的，但是对于一般的应用来说那已经是足够的了，所以你也不必十分苛求。&nbsp; <br />
<br />
&nbsp;&nbsp;小结&nbsp;&nbsp; <br />
&nbsp;&nbsp;本文介绍了在.Net下进行多线程编程所需要掌握的一些基本知识。从文章中我们可以知道在.Net下进行多线程编程相对以前是有了大大的简化，但是其功能并没有被削弱。使用以上的一些基本知识，读者就可以试着编写.Net下的多线程程序了。不过要编写出功能更加强大而且Bug少的多线程应用程序，读者需要掌握诸如线程同步、线程池等高级的多线程编程技术。读者不妨参考一些操作系统方面或是多线程编程方面的技术丛书。
<img src ="http://www.blogjava.net/yank/aggbug/148884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-09-27 21:09 <a href="http://www.blogjava.net/yank/archive/2007/09/27/148884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>结构和类[struct  and   class]</title><link>http://www.blogjava.net/yank/archive/2007/08/23/138808.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Thu, 23 Aug 2007 05:24:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/08/23/138808.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/138808.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/08/23/138808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/138808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/138808.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 结构和类非常相似，但结构是值类型，而类是引用类型。&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/08/23/138808.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/138808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-08-23 13:24 <a href="http://www.blogjava.net/yank/archive/2007/08/23/138808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>结构函数</title><link>http://www.blogjava.net/yank/archive/2007/08/20/138213.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Mon, 20 Aug 2007 11:49:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/08/20/138213.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/138213.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/08/20/138213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/138213.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/138213.html</trackback:ping><description><![CDATA[<p>namespace structHs<br>{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; struct customerName<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string firstName, secondName;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Name()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return firstName + " " + secondName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; class Program<br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; customerName myName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myName.firstName = "Jim";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myName.secondName = "Smith";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(myName.Name());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<img src ="http://www.blogjava.net/yank/aggbug/138213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-08-20 19:49 <a href="http://www.blogjava.net/yank/archive/2007/08/20/138213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DataTable</title><link>http://www.blogjava.net/yank/archive/2007/07/28/133050.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Sat, 28 Jul 2007 13:43:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/07/28/133050.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/133050.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/07/28/133050.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/133050.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/133050.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: [Copy to clipboard] [ - ]CODE:。。。。。SqlDataReader reader1 = cmd1.ExecuteReader ();DataTable dt = reader1 .GetSchemaTable SetColumnHeaders(dt);private void SetColumnHeaders(DataTable schema)//设置表头{&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/07/28/133050.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/133050.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-07-28 21:43 <a href="http://www.blogjava.net/yank/archive/2007/07/28/133050.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>双击硬盘打不开的解决办法</title><link>http://www.blogjava.net/yank/archive/2007/07/26/132635.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Thu, 26 Jul 2007 12:49:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/07/26/132635.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/132635.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/07/26/132635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/132635.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/132635.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 方法二: <br>运行：gpedit.msc打开组策略：用户配置：管理模板：系统：双击：“系统”然后找到右面：关闭自动播放：双击它。然后选已启用：下面的所有驱动器：最后退出。注销一次。或者是重启一次就可以了。。。。 &nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/07/26/132635.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/132635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-07-26 20:49 <a href="http://www.blogjava.net/yank/archive/2007/07/26/132635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取页面的所有TextBox的值</title><link>http://www.blogjava.net/yank/archive/2007/07/25/132411.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Wed, 25 Jul 2007 15:37:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/07/25/132411.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/132411.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/07/25/132411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/132411.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/132411.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 将页面上的所有的TextBox控件的值都置为空&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/07/25/132411.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/132411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-07-25 23:37 <a href="http://www.blogjava.net/yank/archive/2007/07/25/132411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sql语句的模糊查询</title><link>http://www.blogjava.net/yank/archive/2007/07/22/131701.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Sun, 22 Jul 2007 02:16:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/07/22/131701.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/131701.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/07/22/131701.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/131701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/131701.html</trackback:ping><description><![CDATA[SELECT * FROM user WHERE name LIKE ';%三%';<br>将会把name为&#8220;张三&#8221;，&#8220;三脚猫&#8221;，&#8220;唐三藏&#8221;等等有&#8220;三&#8221;的全找出来；<br><br><br>其中LIKE ';%三%'明显多了个分号&#8220;;&#8221;，这还能搜索得出来么？估计是编辑器编译的缘故。<br><br>======重新编辑文如下：<br><br>在进行数据库查询时，有完整查询和模糊查询之分。<br><br>一般模糊语句如下：<br><br>
<table cellSpacing=1 width="100%" bgColor=#cccccc border=0>
    <tbody>
        <tr>
            <td bgColor=#efefef>SELECT 字段 FROM 表 WHERE 某字段 Like 条件<br></td>
        </tr>
    </tbody>
</table>
<br><br>其中关于条件，SQL提供了四种匹配模式：<br><br><strong>1，%</strong>：表示任意0个或多个字符。可匹配任意类型和长度的字符，<font color=#666>有些情况下若是中文，请使用两个百分号（%%）表示</font>。<br><br>比如 SELECT * FROM [user] WHERE u_name LIKE '%三%'<br><br>将会把u_name为&#8220;张三&#8221;，&#8220;张猫三&#8221;、&#8220;三脚猫&#8221;，&#8220;唐三藏&#8221;等等有&#8220;三&#8221;的记录全找出来。<br><br>另外，如果需要找出u_name中既有&#8220;三&#8221;又有&#8220;猫&#8221;的记录，请使用and条件<br>SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%猫%'<br><br>若使用 <font color=#666>SELECT * FROM [user] WHERE u_name LIKE '%三%猫%'</font> <br>虽然能搜索出&#8220;三脚猫&#8221;，但不能搜索出符合条件的&#8220;张猫三&#8221;。<br><br><strong>2，_</strong>： 表示任意单个字符。匹配单个任意字符，它常用来限制表达式的字符长度语句：<br><br>比如 SELECT * FROM [user] WHERE u_name LIKE '_三_'<br>只找出&#8220;唐三藏&#8221;这样u_name为三个字且中间一个字是&#8220;三&#8221;的；<br><br>再比如 SELECT * FROM [user] WHERE u_name LIKE '三__';<br>只找出&#8220;三脚猫&#8221;这样name为三个字且第一个字是&#8220;三&#8221;的；<br><br><br><strong>3，[ ]</strong>：表示括号内所列字符中的一个（类似正则表达式）。指定一个字符、字符串或范围，要求所匹配对象为它们中的任一个。<br><br>比如 SELECT * FROM [user] WHERE u_name LIKE '[张李王]三'<br>将找出&#8220;张三&#8221;、&#8220;李三&#8221;、&#8220;王三&#8221;（而不是&#8220;张李王三&#8221;）；<br><br>如 [ ] 内有一系列字符（01234、abcde之类的）则可略写为&#8220;0-4&#8221;、&#8220;a-e&#8221;<br>SELECT * FROM [user] WHERE u_name LIKE '老[1-9]'<br>将找出&#8220;老1&#8221;、&#8220;老2&#8221;、&#8230;&#8230;、&#8220;老9&#8221;；<br><br><strong>4，[^ ] </strong>：表示不在括号所列之内的单个字符。其取值和 [] 相同，但它要求所匹配对象为指定字符以外的任一个字符。<br><br>比如 SELECT * FROM [user] WHERE u_name LIKE '[^张李王]三'<br>将找出不姓&#8220;张&#8221;、&#8220;李&#8221;、&#8220;王&#8221;的&#8220;赵三&#8221;、&#8220;孙三&#8221;等；<br><br>SELECT * FROM [user] WHERE u_name LIKE '老[^1-4]';<br>将排除&#8220;老1&#8221;到&#8220;老4&#8221;，寻找&#8220;老5&#8221;、&#8220;老6&#8221;、&#8230;&#8230;<br><br><strong>5，查询内容包含通配符时</strong><br><br>由于通配符的缘故，导致我们查询特殊字符&#8220;%&#8221;、&#8220;_&#8221;、&#8220;[&#8221;的语句无法正常实现，而把特殊字符用&#8220;[ ]&#8221;括起便可正常查询。据此我们写出以下函数：<br><br>
<table cellSpacing=1 width="100%" bgColor=#cccccc border=0>
    <tbody>
        <tr>
            <td bgColor=#efefef><br>function sqlencode(str)<br>str=replace(str,"[","[[]") '此句一定要在最前<br>str=replace(str,"_","[_]")<br>str=replace(str,"%","[%]")<br>sqlencode=str<br>end function<br><br></td>
        </tr>
    </tbody>
</table>
<br>在查询前将待查字符串先经该函数处理即可。
<img src ="http://www.blogjava.net/yank/aggbug/131701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-07-22 10:16 <a href="http://www.blogjava.net/yank/archive/2007/07/22/131701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Datalist自定义分页【A】</title><link>http://www.blogjava.net/yank/archive/2007/07/21/131646.html</link><dc:creator>停留的风</dc:creator><author>停留的风</author><pubDate>Sat, 21 Jul 2007 09:31:00 GMT</pubDate><guid>http://www.blogjava.net/yank/archive/2007/07/21/131646.html</guid><wfw:comment>http://www.blogjava.net/yank/comments/131646.html</wfw:comment><comments>http://www.blogjava.net/yank/archive/2007/07/21/131646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yank/comments/commentRss/131646.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yank/services/trackbacks/131646.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Datalist的上下页，首页，尾页，总页码，查询的总结果数<br>这种方法有个缺点：就是利用虚拟的url,在url中有页码的调用&nbsp;&nbsp;<a href='http://www.blogjava.net/yank/archive/2007/07/21/131646.html'>阅读全文</a><img src ="http://www.blogjava.net/yank/aggbug/131646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yank/" target="_blank">停留的风</a> 2007-07-21 17:31 <a href="http://www.blogjava.net/yank/archive/2007/07/21/131646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>