• [WF4.0 实战] AutoResetEvent具体解释(线程独占訪问资源)


    由来:

     

        在学习工作流的过程中,宿主程序中会出现这么一段代码:

               staticAutoResetEvent instanceUnloaded = new AutoResetEvent(false);


        然后就是在方法中这样使用:

               instanceUnloaded.Set();//将事件状态设置为终止状态。同意一个或多个等待线程继续

               instanceUnloaded.WaitOne();//对于WaitOne方法为阻止当前线程,直到收到信号!

     

    对于这部分内容当时不是非常理解,以下我们先介绍一下AutoResetEvent的作用,然后结合工作流分析这些代码的意图。

     

    举个样例:

     

        我去书店买书,当我选中一本书后我会去收费处付钱,付好钱后再去仓库取书。

    这个顺序不能颠倒,我作为主线程,付钱和取书做两个辅助线程

     

    代码例如以下:


    using System;
    using System.Linq;
    using System.Activities;
    using System.Activities.Statements;
    using System.Threading;
     
    namespace CaryAREDemo
    {
        class Me
        {
            const int numIterations = 550;
            static AutoResetEvent myResetEvent = new AutoResetEvent(false);
            static AutoResetEvent ChangeEvent = new AutoResetEvent(false);
            static int number; //这是关键资源
     
    	//主线程 
            static void Main()
            {
                Thread payMoneyThread = new Thread(new ThreadStart(PayMoneyProc));
                payMoneyThread.Name = "付钱线程";
                Thread getBookThread = new Thread(new ThreadStart(GetBookProc));
                getBookThread.Name = "取书线程";
    	    //启动线程
                payMoneyThread.Start();
                getBookThread.Start();
     
                for (int i = 1; i <= numIterations; i++)
                {
                    Console.WriteLine("买书线程:数量{0}", i);
                    number = i;
                    //Signal that a value has been written.
                    //同意线程继续
                    myResetEvent.Set();
                    ChangeEvent.Set();
                    Thread.Sleep(0);
                }
                payMoneyThread.Abort();
                getBookThread.Abort();
            }
     
            static void PayMoneyProc()
            {
                while (true)
                {
    	        //等待满足条件
                    myResetEvent.WaitOne();
                    Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
                }
            }
            static void GetBookProc()
            {
                while (true)
                {
    		//等待满足条件
                    ChangeEvent.WaitOne();                            
                    Console.WriteLine("{0}:数量{1}", Thread.CurrentThread.Name, number);
                    Console.WriteLine("------------------------------------------");
                    Thread.Sleep(0);
                }
            }
        }
    }


    执行结果:

             

    说明:

     

        AutoResetEvent同意线程通过发信号互相通信。通常。此通信涉及线程须要独占訪问的资源。

     

             1,通过将一个布尔值传递给构造函数来控制AutoResetEvent的初始状态。假设初始状态为终止状态,则为 true即该线程堵塞,并等待当前控制资源的线程。否则为 false。

             2,线程也能够通过调用AutoResetEvent 上的 WaitOne 来等待信号。

             3,通过调用 Set发出资源可用的信号。以释放等待线程。

     

        通俗的来讲仅仅有等myResetEven.Set()成功执行后,myResetEven.WaitOne()才可以获得执行机会;Set是发信号。WaitOne是等待信号。仅仅有发了信号,等待的才会执行。

    假设不发的话。WaitOne后面的程序就永远不会执行。

     

     

    结合工作流的宿主程序:

     

    创建工作流:

     

    static AutoResetEvent instanceUnloaded = new AutoResetEvent(false);
     public static Guid CreateAndRun(RequestInfo.RequestInfo Request)
            {
                SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore("server=.;database=aspnetdb;uid=sa;pwd=123456");
    
                InstanceView view = instanceStore.Execute(instanceStore.CreateInstanceHandle(), new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
    
                instanceStore.DefaultInstanceOwner = view.InstanceOwner;
    
                IDictionary<string, object> input = new Dictionary<string, object> 
                {
                    { "Request" , Request }
                };
    
                WorkflowApplication application = new WorkflowApplication(new ApplyBlogFlow(), input);
    
                application.InstanceStore = instanceStore;
    
                //获取或设置当前工作流实例处于空暇状态并可被保留时调用的 ActivityFunc
                application.PersistableIdle = (e) =>
                {
                    instanceUnloaded.Set();
                    return PersistableIdleAction.Unload;
    
                };
                //获取或设置卸载当前工作流
                application.Unloaded = (e) =>
                {
    
                    instanceUnloaded.Set();
    
                };
                //获取或设置当前工作流实例遇到未处理的异常时
                application.OnUnhandledException = (ex) =>
                {
                    Console.Write("Exception");
                    return UnhandledExceptionAction.Terminate;
                };
    
                Guid id = application.Id;
    
                application.Run();
                //阻止当前线程。直到当前waithand收到信号
                instanceUnloaded.WaitOne();
    
                return id;
    
            }
    

        细致看这段代码,在初始时将AutoResetEvent(false),即非终止状态,但是当application.Run();之后就WaitOne,说明此时将AutoResetEvent设置成了终止状态。即堵塞当前线程。为什么要这样呢?目的非常easy。由于这个运行过程为异步,假设当调用启动工作流的方法后,不去阻止当前方法的运行,那么这种方法就这样运行结果,返回我们创建成功,但是问题就是,这个时候非常可能工作流还没有运行完毕,而结果却先告诉我们了。这样显然不合理。

     

    假设大家对于上述的解释还不理解,能够參考下调用流程:

     

             CreateAndRun開始---WaitOne---》当前线程被阻止,即不再往下运行---》真正启动工作流---》工作流运行完等待流后会被设置为空暇状态---PersistableIdle---instanceUnloaded.Set();---AutoResetEvent能够继续--- return id;---》整个方法运行完毕

     

    总结:

     

              AutoResetEvent实现同步,仅仅是众多方法中之中的一个。记得当时在考试系统的教师判分处应用了锁,当时使用的是数据库锁,保证某个表同一时间仅仅能有一个用户在操作,这也是一个实现同步的方式,并且我们在学习java时也知道synchronized实现方法同步等方式。不管是数据库锁,synchronized,还是AutoResetEvent的方式仅仅是它们的側重不同,针对的对象不同,可是目的都是在控制操作的同步进行。


             事实上对于多线程的同步问题就是在程序的运行时多了一步验证(一个门一次仅仅能通过一个即n=1的情况)。是能够运行,还是须要等待而已,对于不同的同步技术仅仅是对不同的对象设置验证。如数据库锁是对表的操作进行限制。


        通过整理发现,事实上AutoResetEvent仅仅是实现同步的一种方式。并没有当时想的那么深奥。关键还是在于对于不懂的知识的学习与整理,了解到它是解决同步的方式后。再结合我们之前使用过的一些同步方法,这些知识就又简单了。所以我们面对学也就开心了。


     


      
  • 相关阅读:
    C#拼音转换,将简体中文转换成拼音
    C#发送邮件
    textBox只能输入汉字
    IOS中UIScrollView的详细使用
    AngularJs学习教程
    IOS-简单计时器的使用
    IOS-多视图控制器之间的切换
    IOS播放音乐和音效
    Nodejs_day04
    Nodejs_day03
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6712999.html
Copyright © 2020-2023  润新知