观察者模式中多线程执行订阅事件并顺序执行的问题

       对事件发布订阅模式中启动线程执行操作,但又要保证线程顺序执行的一些思考和实践,在开发过程中,经常会遇到需要使用事件来触发方法执行的情况,比如CS中按钮的点击事件,鼠标移动事件,键盘监听事件等等,有时候需要执行比较耗时的任务,但并不希望阻塞主线程,导致界面卡顿,使用线程有不能保证线程像同步的执行顺序一样顺序执行,因为有时候事件是系统触发的所以没有办法等待,所以在这儿记录下这个解决思路。

模拟情景:模拟事件订阅的方法被多线程执行。

首先声明一个TaskEventQueue类并使用单例模式,公开Regist方法,默认通过启用线程的方式执行订阅的方法,公开Invoke方法来发布事件。

通过下面的方式订阅事件,现在遇到的问题是订阅的方法不能按顺序执行 ,

所以我考虑使用延续任务,来解决这一问题。

修改构造函数并添加一个Task属性,延续任务必须是上一个任务处于正常执行完毕退出的状态才能生效。

修改Regist方法通过重复指向的方式不断叠加延续任务。

此时输出的结果为:

普通的主线程执行结果为:

疑惑:是否有必要这么做?

有时候会想,为什么不直接在发布事件时开一个线程执行呢?修改代码,试一下是可以的

答案是可以的,结果确实会顺序执行,结果为:

但这是我们自己的代码可以随意更改,如果是系统发布的事件,就不是我们能干涉的了,不能要求系统也这么做。

上述的方式其实只适用于业务场景并发量小的情况,在bs服务端暂时还没有这样的需求,但CS端可能会遇到。

注意:当前模拟场景中事件的发布假设是无法更改的。

代码部分:

public class TaskEventQueue
    {
        TaskEventQueue()
        {
            ComplateTask = new Task(() => { });
            ComplateTask.Start();
        }

        volatile Task ComplateTask;

        public event Action SampleEvent;

        volatile static TaskEventQueue taskEventQueue;
 public static TaskEventQueue GetSingletionInstance()=>taskEventQueue??(taskEventQueue = new TaskEventQueue());

        public void Regist(Action action)
        {
            //SampleEvent += action;//主线程同步执行方式
            SampleEvent += () =>//采用多线程方式
            {
                if (action == null)
                {
                    throw new ArgumentException();
                }
                ComplateTask = ComplateTask.ContinueWith(t => action());
            };
        }

        public void Invok()
        {
            SampleEvent.Invoke();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值