实例代码讲解c# 线程(下)
前言
实例代码讲解c#线程(上)
使用Mutex类
classProgram { staticvoidMain(string[]args) { conststringMutexName="CSharpThreadingCookbook"; using(varm=newMutex(false,MutexName)) { if(!m.WaitOne(TimeSpan.FromSeconds(5),false)) { Console.WriteLine("Secondinstanceisrunning!"); } else{ Console.WriteLine("Runing!"); Console.ReadLine(); m.ReleaseMutex(); } } } }
当主程序启动时,定义了一个指定名称的互斥量,设置initialowner标志为false。这意味着如果互斥量已经被创建,则允许程序获取该互斥量。如果没有获取到互斥量,程序则简单的显示running,的等待知道按下了任何键,然后释放该互斥量并退出。如果再运行同样一个程序,则会在5秒内尝试获取互斥量。如果此时在第一个程序中按下了任何键,第二个程序则会开始执行。然而,如果保持等待5秒钟,第二个程序将无法获取到该互斥量。该方式可用于在不同的程序中同步线程,可被推广到大量的使用场景中。
使用SemaphoreSilm类
staticSemaphoreSlim_semaphore=newSemaphoreSlim(4); staticvoidAccessDatabase(stringname,intseconds){ Console.WriteLine("{0}waitstoaccessadatabase",name); _semaphore.Wait(); Console.WriteLine("{0}wasgrantedanaccesstoadatabase",name); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("{0}iscompleted",name); _semaphore.Release(); }
staticvoidMain(string[]args) { for(inti=1;i<=6;i++){ stringthreadName="Thread"+i; intsecondsToWait=2+2*i; vart=newThread(()=>AccessDatabase(threadName,secondsToWait)); t.Start(); } Console.ReadKey(); }
当主程序启动时,创建了SemaphoreSlim的一个实例,并在其构造函数中指定允许的并发线程数量。然后启动了6个不同名称和不同初始运行时间的线程。每个线程都尝试获取数据库的访问,但是我们借助于信号系统限制了访问数据库的并发数为4个线程。当有4个线程获取数据库的访问后,其他两个线程需要等待,直到之前线程中的某一个完成工作并调用_semaphore.Release方法来发出信号。
使用AutoResetEvent类
privatestaticAutoResetEvent_workerEvent=newAutoResetEvent(false); privatestaticAutoResetEvent_mainEvent=newAutoResetEvent(false); staticvoidProcess(intseconds) { Console.WriteLine("Startingalongrunningwork..."); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("Workisdone!"); _workerEvent.Set(); Console.WriteLine("Waitingforamainthreadtocompleteitswork"); _mainEvent.WaitOne(); Console.WriteLine("startingsecondoperation..."); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("Workisdone!"); _workerEvent.Set(); }
staticvoidMain(string[]args) { vart=newThread(()=>Process(10)); t.Start(); Console.WriteLine("Waitingforamainthreadtocompleteitswork"); _workerEvent.WaitOne(); Console.WriteLine("Firstoperationiscompleted!"); Console.WriteLine("Performinganoperationonamainthread"); Thread.Sleep(TimeSpan.FromSeconds(5)); _mainEvent.Set(); Console.WriteLine("Nowrunningthesecondoperationonasecondthread"); _workerEvent.WaitOne(); Console.WriteLine("Secondoperationiscompleted!"); }
当主程序启动时,定义了两个autoresetEvent实例。其中一个是从子线程向主线程发信号,另一个实例是从主线程向子线程发信息号。我们向AutoResetEvent构造方法传入false,定义了这两个实例初始状态为unsignaled。这意味着我们任何线程调用这两个对象中的任何一个waitone方法将会被堵塞,直到我们调用了set方法。如果初试事件为true,那么autoresetEvent实例的状态为sigaled,如果线程调用waitone方法则会立即处理。然后事件状态自动变为unsignaled,所以需要再对改实例调用一次set方法,以便让其他的线程对该实例调用waitone方法从而继续执行。然后我们创建了第二个线程,其会执行第一个操作10秒钟,然后等待从第二个线程发出的信号。该信号意味着第一个操作已经完成。现在第二个线程在等待主线程的信号,我们对主线程做了一些1附加工作,并通过调用_mainEvent.Set方法发送了一个信号。然后等待从第二个线程发出的另一个信号AutoResetEvent类采用的是内核时间模式,所以等待时间不能太长。使用2.6节中的ManualResetEventslim类更好,因为他使用的是混合模式。
以上就是实例代码讲解c#线程(下)的详细内容,更多关于c#线程的资料请关注毛票票其它相关文章!