关于互斥执行的设计与实现

引言

我在开发过程中经常遇到这样一个问题(简化版描述):一个文本框绑定了TextChanged事件,在另一个方法中我想要改变文本框的值却不想触发TextChanged事件。

一般会使用如下方案解决:

1. 先注销TextChanged事件,赋值完重新绑定:

void A_TextChanged(object sender, EventArgs e)
{
    A.TextChanged -= A_TextChanged;
    // do something.
    A.Text = "Hello world!";
    // do something.
    A.TextChanged += A_TextChanged;
}

void B_TextChanged(object sender, EventArgs e)
{
    A.TextChanged -= A_TextChanged;
    // do something.
    A.Text = "Hello world!";
    // do something.
    A.TextChanged += A_TextChanged;
}

2. 通用标记isEditing,此时可以适用于多种场景:

bool isEditing = false;
void A_TextChanged(object sender, EventArgs e)
{
    if (isEditing)
        return;
    isEditing = true;
    // do something.
    A.Text = "Hello world!";
    // do something.
    isEditing = false;
}
void B_TextChanged(object sender, EventArgs e)
{
    if (isEditing)
        return;
    isEditing = true;
    // do something.
    A.Text = "Hello world!";
    // do something.
    isEditing = false;
}

引言小结: 两种方法均采用解绑-执行-绑定的思路,虽然能达到预期的效果,但是实现的冗余代码量太大,感觉很痛苦。

正文

开发就是这样,常常在灵光一闪的瞬间,你忽然就有了一种解决问题的思路,这种感觉很让人欣喜若狂。

Idea描述:简化解绑-绑定的过程,例如做到像using关键字那样,执行后自动释放对象。而此时,我想到了“锁”这个概念。锁,对于开发来说,常用与多线程的同步、对资源的锁定或者是资源的互斥,如XXXResetEvent、Lock关键字、Mutex。

设计思路:在方法开始时记录一个Tag标记,若该Tag已经在使用,则return,否则继续执行。

简化版实现:

public class ExclusiveLock
{
    private static Dictionary<object, bool> TagMap = new Dictionary<object, bool>();

    public static void Run(object tag, Action action)
    {
        if (tag != null)
        {
            if (!TagMap.ContainsKey(tag))
            {
                TagMap.Add(tag, false);
            }

            if (!TagMap[tag])
            {
                TagMap[tag] = true;
                action();
                TagMap[tag] = false;
            }
        }
        else
        {
            throw new NullReferenceException("参数tag不能为Null值。");
        }
    }
}
void A_TextChanged(object sender, EventArgs e)
{
    ExclusiveLock.Run(this, () =>
    {
        // do something.
        A.Text = "Hello world!";
        // do something.
    });
}
void B_TextChanged(object sender, EventArgs e)
{
    ExclusiveLock.Run(this, () =>
    {
        // do something.
        A.Text = "Hello world!";
        // do something.
    });
}

正文小结:当执行B方法时,将记录Tag为this的信号为true,此时为A赋值,会触发A_TextInput事件,但由于Tag为this的信号已经存在,所以不会执行Action中的代码。

总结

这个设计模式主要借鉴互斥信号量的思想,当一个信号存在的时候,其他与该信号相同的任务均不执行。在最大限度上简化了冗余代码。但设计难免总会有疏漏与不足,若您有任何问题,欢迎留言探讨,共同寻求更优的解决方案。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-03 21:34:09

关于互斥执行的设计与实现的相关文章

Java并发原语——线程、互斥与同步

本文将介绍: Java线程基本操作(创建.等待等) Java线程同步原语(同步.互斥) 如果你对以上话题已了如指掌,请止步. Java线程基本操作 Java的线程API以java.lang.Thread类提供,线程的基本操作被封装为为Thread类的方法,其中常用的方法是:   方法 说明 void start() 启动线程 void join() 等待线程结束 创建(启动)线程 Java中,创建线程的过程分为两步: 创建可执行(Runnable)的线程对象: 调用它的start()方法: 可执

游戏开发——战斗系统之技能设计

现在在做的项目大致分为两块:战斗系统和除战斗系统之外的(简称外围系统),而我一直在做的是外围系统的开发,至少在6月份返校毕业答辩之前没有动过战斗系统.答辩回来之后很长一段时间内也是在做外围系统的bug修复,可是由于种种原因项目赶不上所谓的进度了,上周五主管问我和另外一个也主要负责外围系统开发的同事谁更忙,我一句我没啥事干,结果主管说战斗系统的主动技能让我来做.这周一开会负责人一纸任务安排扔下来,上面写着XX同事这周完成主动技能的开发及相关系统的bug修复,还说没完成任务就XXX,此处省略XX字.

进程互斥与同步

一.进程互斥 首先我们要知道,为了保证程序执行最终结果的正确性,必须对并发执行的各进程进行制约,以控制它们的执行速度和对资源的竞争.需要回到一个问题,需要对程序哪些部分进行制约才能保证其执行结果的正确性?如:进程PA 和PB共享内存 MS,进程PA 和PB 各执行两条语句时,可能按以下顺序执行:当进程PA执行完第一条语句,开始执行进程PB,再接着执行进程PA 的第二条语句.这样会导致错误.如何保证正确性了?我们可以将各自的两条语句抽象为两个各以一个动作完成的顺序执行单位,这样执行结果的正确性就可

设计CTime类,并且在CTime类中使用运算符重载

程序代码: #include <iostream> using namespace std; class CTime//时间类 { private: unsigned short int hour; //时 unsigned short int minute; //分 unsigned short int second; //秒 public: CTime(int h=0,int m=0,int s=0);//构造函数 void setTime(int h,int m,int s);//设置时

同步互斥

1.原子操作 2.临界区概述 临界区:进程中访问临界资源的一段需要互斥执行的代码. 进入区:检查可否进入临界区的一段代码,如可进入,设置相应“正在访问临界区”标志. 退出区:清除“正在访问临界区”标志. 3.临界区访问规则 空闲则入:没有进程在临界区时,任何进程可进入. 忙则等待:有进程在临界区时,其他进程均不能进入临界区. 有限等待:等待进入临界区的进程不能无限期等待. 让权等待(可选):不能进入临界区的进程,应释放CPU(如转换到阻塞状态). 4.临界区的实现方法: 不同的临界区实现机制的比

模块管理常规功能自定义系统的设计与实现(19--模块附件的设计[2])

模块附件的设计(2) 上一节中介绍了附件的操作,对于附件我们一般认为都是加在模块的记录之上的.但是客户提出了附件要加在字段上的想法,我考虑了一下,给他解释完全可以用附件的类型来区分这个附件是加在哪个字段之上的,可是他不同意,于是就有了附件加在字段之上的设计(客户真是扩展需求分析的唯一途径). 由于这套系统是完全解释型的,因此加入的这个功能也只需配置一下,然后解释执行就行.经过分析,我在模块字段中加了一个"字段附件"的boolean型的字段.将此字段值置为true,表示这个字段可以加入附

软测之魂核心测试设计精解pdf

下载地址:网盘下载 <软测之魂:核心测试设计精解>内容简介:测试界有不少朋友都认为,测试设计不就是测试用例的设计吗?这样的回答是不全面的,用例设计只是其中的一项重要内容.测试设计是一个过程,它贯穿在软件生命周期的各个环节,是测试丁作的核心.灵魂所存. <软测之魂:核心测试设计精解>以测试设计为主线,首先介绍了软件测试行业在过去十多年来的发展变化,如今,实实在在地发生在我们身边的一起起软件质量事故,无不昭示着软件测试行业朝阳的到来.如何把握测试技术,把测试工作做得精透,成为测试行业的

设计,架构,框架之间是什么关系?

设计(design).架构(architechure).框架 (framework)之间是个什么关系?请描述一下? 每个人都在进行设计 在探讨题目问题之前,我们从设计开始聊聊. 其实我们每个人都在做设计,无论我们是在哪个行业,哪个层次,哪个职位. 画家作画时会画草图做设计 作家写作时会列提纲做设计 程序员编码时会写伪代码做设计 清洁工扫地时会在脑海里设计扫地的执行路径 设计有大有小 对于软件系统领域来说: 在方法层次,我们可以设计方法名.变量名.语句块使得方法变得易懂.简洁.高效: 在类的层次,

测试方法和测试用例设计

测试方法和测试用例设计 用户需求/原始需求 需求分析/规格说明书(评审过后,将不合理.无法做到的地方去掉以后的说明书) 测试需求(在需求分析的基础上,以测试团队的工作计划.方式的需要.工作优先级安排) 主要解决"测什么"的问题,即指明被测对象中什么需要测试. 功能是第一要务,按照测试团队的工作要求进行计划 在后期交流中,要不断验证客户需求,要保留文档 对于测试工程师:测试一般划分为功能性测试.非功能性测试 如果没有需求文档,先做冒烟测试,对软件大体有什么功能,进行了解,哪些是功能的重点