• C#线程(二)


    使用Mutex类

                    class Program
                    {
                        static void Main(string[] args)
                    {
                    const string MutexName ="CSharpThreadingCookbook";
                    using (var m = new Mutex(false, MutexName))
                    {
                    if (!m.WaitOne(TimeSpan.FromSeconds(5), false))
                    {
                        Console.WriteLine("Second instance is running!");
                    }
                    else {
                        Console.WriteLine("Runing!");
                        Console.ReadLine();
                        m.ReleaseMutex();
                    }
                }
            }
        }
                
    当主程序启动时,定义了一个指定名称的互斥量,设置initialowner标志为false。这意味着如果互斥量已经被创建,则允许程序获取该互斥量。如果没有获取到互斥量,程序则简单的显示running,的等待知道按下了任何键,然后释放该互斥量并退出。 如果再运行同样一个程序,则会在5秒内尝试获取互斥量。如果此时在第一个程序中按下了任何键,第二个程序则会开始执行。然而,如果保持等待5秒钟,第二个程序将无法获取到该互斥量。 该方式可用于在不同的程序中同步线程,可被推广到大量的使用场景中。

    使用SemaphoreSilm类

                static SemaphoreSlim _semaphore = new SemaphoreSlim(4);
    
                static void AccessDatabase(string name, int seconds) {
                Console.WriteLine("{0} waits to access a database",name);
                _semaphore.Wait();
                Console.WriteLine("{0} was granted an access to a database",name);
                Thread.Sleep(TimeSpan.FromSeconds(seconds));
                Console.WriteLine("{0} is completed",name);
                _semaphore.Release();
    
            }
            
                 static void Main(string[] args)
                {
                for (int i = 1; i <= 6; i++) {
                    string threadName ="Thread" + i;
                    int secondsToWait = 2 + 2 * i;
                    var t = new Thread(() => AccessDatabase(threadName, secondsToWait));
                    t.Start();
                }
                Console.ReadKey();
            }
            
    当主程序启动时,创建了SemaphoreSlim的一个实例,并在其构造函数中指定允许的并发线程数量。然后启动了6个不同名称和不同初始运行时间的线程。每个线程都尝试获取数据库的访问,但是我们借助于信号系统限制了访问数据库的并发数为4个线程。当有4个线程获取数据库的访问后,其他两个线程需要等待,直到之前线程中的某一个完成工作并调用_semaphore.Release方法来发出信号。

    使用AutoResetEvent类

                private staticAutoResetEvent _workerEvent=new AutoResetEvent(false);
                private staticAutoResetEvent _mainEvent =new AutoResetEvent(false);
                static void Process(int seconds)
                {
                    Console.WriteLine("Starting a long running work... ");
                    Thread.Sleep(TimeSpan.FromSeconds(seconds));
                    Console.WriteLine("Work is done!");
                    _workerEvent.Set();
                    Console.WriteLine("Waiting for a main thread to complete its work");
                    _mainEvent.WaitOne();
                    Console.WriteLine("starting second operation... ");
                    Thread.Sleep(TimeSpan.FromSeconds(seconds));
                    Console.WriteLine("Work is done!");
                    _workerEvent.Set();
            }
            
                static void Main(string[] args)
                {
                    var t = new Thread(() => Process(10));
                    t.Start();
                    Console.WriteLine("Waiting for a main thread to complete its work");
                    _workerEvent.WaitOne();
                    Console.WriteLine("First operation is completed!");
                    Console.WriteLine("Performing an operation on a main thread");
                    Thread.Sleep(TimeSpan.FromSeconds(5));
                    _mainEvent.Set();
                    Console.WriteLine("Now running the second operation on a second thread");
                    _workerEvent.WaitOne();
                    Console.WriteLine("Second operation is completed!");
            }
            
    当主程序启动时,定义了两个autoresetEvent实例。其中一个是从子线程向主线程发信号,另一个实例是从主线程向子线程发信息号 。我们向AutoResetEvent构造方法传入false,定义了这两个实例初始状态为unsignaled。这意味着我们任何线程调用这两个对象中的任何一个 waitone方法将会被堵塞,直到我们调用了set方法。如果初试事件为true,那么autoresetEvent实例的状态为sigaled,如果线程调用waitone方法则会立即处理。 然后事件状态自动变为unsignaled,所以需要再对改实例调用一次set方法,以便让其他的线程对该实例调用waitone方法从而继续执行。 然后我们创建了第二个线程,其会执行第一个操作10秒钟,然后等待从第二个线程发出的信号。该信号意味着第一个操作已经完成。现在第二个线程在 等待主线程的信号,我们对主线程做了一些1附加工作,并通过调用_mainEvent.Set方法发送了一个信号。然后等待从第二个线程发出的另一个信号 AutoResetEvent类采用的是内核时间模式,所以等待时间不能太长。使用2.6节中的ManualResetEventslim类更好,因为他使用的是混合模式。
  • 相关阅读:
    November 13th 2016 Week 47th Sunday The 1st Day
    November 12th 2016 Week 46th Saturday
    November 11th 2016 Week 46th Friday
    November 10th 2016 Week 46th Thursday
    November 9th 2016 Week 46th Wednesday
    November 8th 2016 Week 46th Tuesday
    windows 7文件共享方法
    Win7无线网络共享设置方法
    常量指针和指针常量
    如何查找局域网的外网ip
  • 原文地址:https://www.cnblogs.com/yyfh/p/7338912.html
Copyright © 2020-2023  润新知