??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
]]>
开始新U程
?Net下创Z个新U程是非常容易的Q你可以通过以下的语句来开始一个新的线E:
Thread thread = new Thread (new ThreadStart (ThreadFunc));
thread.Start ();
W一条语句创Z个新的Thread对象Qƈ指明了一个该U程的方法。当新的U程开始时Q该Ҏ也就被调用执行了。该U程对象通过一个System..Threading.ThreadStartcȝ一个实例以cd安全的方法来调用它要调用的线E方法?nbsp;
W二条语句正式开始该新线E,一旦方法StartQ)被调用,该线E就保持在一?alive"的状态下了,你可以通过d它的IsAlive属性来判断它是否处?alive"状态。下面的语句昄了如果一个线E处?alive"状态下将该线E挂LҎQ?nbsp;
if (thread.IsAlive) {
thread.Suspend ();
}
不过h意,U程对象的StartQ)Ҏ只是启动了该U程Q而ƈ不保证其U程ҎThreadFuncQ)能立卛_到执行。它只是保证该线E对象能被分配到CPU旉Q而实际的执行q要由操作系l根据处理器旉来决定?nbsp;
一个线E的Ҏ不包含Q何参敎ͼ同时也不q回M倹{它的命名规则和一般函数的命名规则相同。它既可以是静态的QstaticQ也可以是非静态的QnonstaticQ。当它执行完毕后Q相应的U程也就l束了,其线E对象的IsAlive属性也p|ؓfalse了。下面是一个线E方法的实例Q?nbsp;
public static void ThreadFunc()
{
for (int i = 0; i <10; i++) {
Console.WriteLine("ThreadFunc {0}", i);
}
}
前台U程和后台线E?nbsp;
.Net的公用语aq行ӞCommon Language RuntimeQCLRQ能区分两种不同cd的线E:前台U程和后台线E。这两者的区别是Q应用程序必运行完所有的前台U程才可以退出;而对于后台线E,应用E序则可以不考虑其是否已l运行完毕而直接退出,所有的后台U程在应用程序退出时都会自动l束?nbsp;
一个线E是前台U程q是后台U程可由它的IsBackground属性来军_。这个属性是可读又可写的。它的默认gؓfalseQ即意味着一个线E默认ؓ前台U程。我们可以将它的IsBackground属性设|ؓtrueQ从而之成Z个后台线E?nbsp;
下面的例子是一个控制台E序Q程序一开始便启动?0个线E,每个U程q行5U钟旉。由于线E的IsBackground属性默认ؓfalseQ即它们都是前台U程Q所以尽程序的ȝE很快就q行l束了,但程序要到所有已启动的线E都q行完毕才会l束。示例代码如下:
using System;
using System.Threading;
class MyApp
{
public static void Main ()
{
for (int i=0; i<10; i++) {
Thread thread = new Thread (new ThreadStart (ThreadFunc));
thread.Start ();
}
}
private static void ThreadFunc ()
{
DateTime start = DateTime.Now;
while ((DateTime.Now - start).Seconds <5)
;
}
}
接下来我们对上面的代码进行略微修改,每个线E的IsBackground属性都讄为trueQ则每个U程都是后台U程了。那么只要程序的ȝE结束了Q整个程序也q束了。示例代码如下:
using System;
using System.Threading;
class MyApp
{
public static void Main ()
{
for (int i=0; i<10; i++) {
Thread thread = new Thread (new ThreadStart (ThreadFunc));
thread.IsBackground = true;
thread.Start ();
}
}
private static void ThreadFunc ()
{
DateTime start = DateTime.Now;
while ((DateTime.Now - start).Seconds <5)
;
}
}
既然前台U程和后台线E有q种差别Q那么我们怎么知道该如何设|一个线E的IsBackground属性呢Q下面是一些基本的原则Q对于一些在后台q行的线E,当程序结束时q些U程没有必要l箋q行了,那么q些U程应该设|ؓ后台U程。比如一个程序启动了一个进行大量运的U程Q可是只要程序一旦结束,那个U程失Ml箋存在的意义,那么那个U程p是作为后台线E的。而对于一些服务于用户界面的线E往往是要讄为前台线E的Q因为即使程序的ȝE结束了Q其他的用户界面的线E很可能要l存在来昄相关的信息,所以不能立即终止它们。这里我只是l出了一些原则,具体到实际的q用往往需要编E者的q一步仔l斟酌?nbsp;
U程优先U?nbsp;
一旦一个线E开始运行,U程调度E序可以控制其所获得的CPU旉。如果一个托的应用E序q行在Windows机器上,则线E调度程序是由Windows所提供的。在其他的^CQ线E调度程序可能是操作pȝ的一部分Q也自然可能?Net框架的一部分。不q我们这里不必考虑U程的调度程序是如何产生的,我们只要知道通过讄U程的优先我们可以该线E获得不同的CPU旉?nbsp;
U程的优先是由Thread.Priority属性控制的Q其值包含:ThreadPriority.Highest、ThreadPriority.AboveNormal、ThreadPriority.Normal、ThreadPriority.BelowNormal和ThreadPriority.Lowest。从它们的名UC我们自然可以知道它们的优先程度,所以这里就不多作介l了?nbsp;
U程的默认优先为ThreadPriority.Normal。理ZQ具有相同优先的线E会获得相同的CPU旉Q不q在实际执行Ӟ消息队列中的U程d或是操作pȝ的优先的提高等原因会导致具有相同优先的线E会获得不同的CPU旉。不q从M上来考虑仍可以忽略这U差异。你可以通过以下的方法来改变一个线E的优先U?nbsp;
thread.Priority = ThreadPriority.AboveNormal;
或是Q?nbsp;
thread.Priority = ThreadPriority.BelowNormal;
通过上面的第一句语句你可以提高一个线E的优先U,那么该线E就会相应的获得更多的CPU旉Q通过W二句语句你侉K低了那个U程的优先Q于是它׃被分配到比原来少的CPU旉了。你可以在一个线E开始运行前或是在它的运行过E中的Q何时候改变它的优先。理Z你还可以L的设|每个线E的优先U,不过一个优先q高的线E往往会媄响到其他U程的运行,甚至影响到其他程序的q行Q所以最好不要随意的讄U程的优先?nbsp;
挂vU程和重新开始线E?nbsp;
Threadcd别提供了两个Ҏ来挂LE和重新开始线E,也就是Thread.Suspend能暂停一个正在运行的U程Q而Thread.Resume又能让那个线El运行。不像Windows内核Q?Net框架是不记录U程的挂h数的Q所以不你挂vU程q几ơ,只要一ơ调用Thread.Resume可以让挂v的线E重新开始运行?nbsp;
Threadc还提供了一个静态的Thread.SleepҎQ它能一个线E自动的挂v一定的旉Q然后自动的重新开始。一个线E能在它自n内部调用Thread.SleepҎQ也能在自n内部调用Thread.SuspendҎQ可是一定要别的U程来调用它的Thread.ResumeҎ才可以重新开始。这一Ҏ不是很容易想通的啊?下面的例子显CZ如何q用Thread.SleepҎQ?nbsp;
while (ContinueDrawing) {
DrawNextSlide ();
Thread.Sleep (5000);
}
l止U程
在托的代码中,你可以通过以下的语句在一个线E中另一个线E终止掉Q?nbsp;
thread.Abort ();
下面我们来解释一下AbortQ)Ҏ是如何工作的。因为公用语aq行时管理了所有的托管的线E,同样它能在每个线E内抛出异常。AbortQ)Ҏ能在目标U程中抛Z个ThreadAbortException异常从而导致目标线E的l止。不qAbortQ)Ҏ被调用后Q目标线E可能ƈ不是马上q止了。因为只要目标线E正在调用非托管的代码而且q没有返回的话,该线E就不会立即l止。而如果目标线E在调用非托的代码而且陷入了一个死循环的话Q该目标U程根本不会终止。不q这U情况只是一些特例,更多的情冉|目标U程在调用托的代码Q一旦AbortQ)被调用那么该U程q即终止了?nbsp;
在实际应用中Q一个线E终止了另一个线E,不过往往要等那个U程完全l止了它才可以l运行,q样的话我们应该用到它的JoinQ)Ҏ。示例代码如下:
thread.Abort (); // 要求l止另一个线E?nbsp;
thread.Join (); // 只到另一个线E完全终止了Q它才l运?nbsp;
但是如果另一个线E一直不能终止的话(原因如前所qͼQ我们就需要给JoinQ)Ҏ讄一个时间限ӞҎ如下Q?nbsp;
thread.Join (5000); // 暂停5U?nbsp;
q样Q在5U后Q不那个线E有没有完全l止Q本U程强行运行了。该Ҏq返回一个布型的|如果是true则表明那个线E已l完全终止了Q而如果是false的话Q则表明已经过了时间限制了?nbsp;
旉U程
.Net框架中的Timercd以让你用时钟线E,它是包含在System.Threading名字I间中的Q它的作用就是在一定的旉间隔后调用一个线E的Ҏ。下面我l大家展CZ个具体的实例Q该实例?Uؓ旉间隔Q在控制C输出不同的字W串Q代码如下:
using System;
using System.Threading;
class MyApp
{
private static bool TickNext = true;
public static void Main ()
{
Console.WriteLine ("Press Enter to terminate...");
TimerCallback callback = new TimerCallback (TickTock);
Timer timer = new Timer (callback, null, 1000, 1000);
Console.ReadLine ();
}
private static void TickTock (object state)
{
Console.WriteLine (TickNext ? "Tick" : "Tock");
TickNext = ! TickNext;
}
}
从上面的代码中,我们知道W一个函数回调是?000毫秒后才发生的,以后的函数回调也是在每隔1000毫秒之后发生的,q是由Timer对象的构造函C的第三个参数所军_的。程序会?000毫秒的时间间隔后不断的生新U程Q只到用戯入回车才l束q行。不q值得注意的是Q虽然我们设|了旉间隔?000毫秒Q但是实际运行的时候往往q不能非常精。因为Windows操作pȝq不是一个实时系l,而公用语aq行时也不是实时的,所以由于线E调度的千变万化Q实际的q行效果往往是不能精到毫秒U的Q但是对于一般的应用来说那已l是_的了Q所以你也不必十分苛求?nbsp;
结
本文介绍了在.Net下进行多U程~程所需要掌握的一些基本知识。从文章中我们可以知道在.Net下进行多U程~程相对以前是有了大大的化,但是其功能ƈ没有被削弱。用以上的一些基本知识,读者就可以试着~写.Net下的多线E程序了。不q要~写出功能更加强大而且Bug的多线E应用程序,读者需要掌握诸如线E同步、线E池{高U的多线E编E技术。读者不妨参考一些操作系l方面或是多U程~程斚w的技术丛书?
]]>
]]>
{
struct customerName
{
public string firstName, secondName;
public string Name()
{
return firstName + " " + secondName;
}
}
class Program
{
static void Main(string[] args)
{
customerName myName;
myName.firstName = "Jim";
myName.secondName = "Smith";
Console.WriteLine(myName.Name());
Console.ReadKey();
}
}
}
SELECT 字段 FROM ?WHERE 某字D?Like 条g |
function sqlencode(str) str=replace(str,"[","[[]") '此句一定要在最?br>str=replace(str,"_","[_]") str=replace(str,"%","[%]") sqlencode=str end function |