由来:

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

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);
            }
        }
    }
}

执行结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqaW5neXVhbjY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

说明:

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

[WF4.0 实战] AutoResetEvent具体解释(线程独占訪问资源)的更多相关文章

  1. 【转】WF4.0实战系列索引

    转自:http://www.cnblogs.com/zhuqil/archive/2010/07/05/wf4-in-action-index.html 此系列的工作流文件案例比较多点,实用性好. W ...

  2. Java中怎么控制线程訪问资源的数量

    在API中是这样来描写叙述Semaphore 的 Semaphore 通经常使用于限制能够訪问某些资源(物理或逻辑的)的线程数目. 一个计数信号量.从概念上讲,信号量维护了一个许可集.如有必要,在许可 ...

  3. java使用线程请求訪问每次间隔10分钟连续5次,之后停止请求

    java使用线程请求訪问每次间隔10分钟连续5次,收到对应的时候停止请求 package com.qlwb.business.util; /** * * * @类编号: * @类名称:RequestT ...

  4. [WF4.0 实战] WPF + WCF + WF 打造Hello World(基础篇)

    本篇博客是一个基础的演示样例,也就是一个新手教程吧!让大家熟悉一下WPF + WCF + WF三者的关系!这仅仅是一个基础篇,下篇会继续深入,作为这段时间研究工作流的一个小小总结! 三者关系: WPF ...

  5. [WF4.0 实战] 事件驱动应用

    看到题目或许非常多人都会疑问,为什么要使用事件监听呢? 眼下的认识: 1,使用事件监听能够将工作流的结点返回值返回到client 2,能够实现等待与重新启动,相当于之前的WaitActivity创建B ...

  6. android 4.0主线程訪问网络问题

    在4.0下面,在主线程中訪问网络,假设请求超过6s的话,就会报ANR,那么这就会带来一个问题,假设网络慢或者请求的数据过大时,界面会卡顿,造成界面灵敏性非常差,因此网络请求一般不能放在主线程中操作,g ...

  7. 【转】WF4.0 (基础篇)

    转自:http://www.cnblogs.com/foundation/category/215023.html 作者:WXWinter  ——  兰竹菊梅★春夏秋冬☆ —— wxwinter@16 ...

  8. WF4.0 基础篇 (一)开始使用WF

    来源:https://www.cnblogs.com/caosenianhuan/p/WF.html 最近公司要重新上线一套新的CRM系统,要重整老系统里的业务流模块,团队讨论已微软的workflow ...

  9. ETL工具--DataX3.0实战

    DataX是一个在异构的数据库/文件系统之间高速交换数据的工具,实现了在任意的数据处理系统(RDBMS/Hdfs/Local filesystem)之间的数据交换,由淘宝数据平台部门完成. DataX ...

随机推荐

  1. bss段,代码段及数据段,堆栈段的区别

    bss段,代码段及数据段,堆栈段的区别 时间:2012-11-21 10:0772人阅读 BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英 ...

  2. JavaScript-jQuery报TypeError $(...) is null错误(jQuery失效)解决办法

    出现这种错误一般都是jQuery的$方法被覆盖, 解决办法: 1.把$改为jQuery使用 jQuery.noConflict();//将变量$的控制权让渡给给其他插件或库 jQuery(functi ...

  3. 如何解决普通用户使用sudo找不到命令

    一.在linux的普通用户下,要使用root权限的命令需要使用sudo [dev@dev1 client_api]# sudo git pull origin develop sudo: git: c ...

  4. java多线程(五)之总结(转)

    引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...

  5. Servlet乱码问题

    数据像水流一样从一个地方流向另一个地方. 文本流是特殊的二进制流. 既然提到乱码问题,那就必然是用错误的编码去解释二进制流. 在传输过程中必然都是以二进制流传输的. 所以,我们需要考虑的是: 有几个数 ...

  6. 使用自定义模板来弥补eclipse没有新建Filter的功能

    http://yufei.iteye.com/blog/125012 eclipse插件,并没有为我们提供Filter的新建功能,为此我们不得不每次都去新建个类,然后输入那繁琐的重复代码,这完全就是浪 ...

  7. python matplotlib.pyplot画矩形图 以及plt.gca()

    plt的Rectangle参数: 第一个参数是坐标(x,y),即矩形的画图的起点坐标,这个起点坐标不是一味地从左下角开始画,而是对应整个图中坐标原点,即(0,0). 第二个参数是矩形宽度 第三个坐标是 ...

  8. Java和C++通过Socket通信中文乱码的解决

    理想的开发状态是我开始就是C开发,一直是C的开发,现在还是C的开发,若干年后,幸运的话,我可以成为C语言的高手或者专家…… 更实际的情况是我开始是C开发,后来变成了JAVA开发,然后又做起了VC++的 ...

  9. python标准库介绍——6 math模块详解

    ==math 模块== ``math`` 模块实现了许多对浮点数的数学运算函数. 这些函数一般是对平台 C 库中同名函数的简单封装, 所以一般情况下, 不同平台下计算的结果可能稍微地有所不同, 有时候 ...

  10. unity5, Configurable Joint: Anchor, Connected Anchor, Auto Configure Connected Anchor

    configurable joint加在轮子上,connected body是车身. 这种情况下,Anchor=(0,0,0)表示轮子一端joint锚点取carWheelCenter Connecte ...