[.NET] Thread Separate Event

本文探讨了多线程环境中实现事件按顺序处理的方法。通过引入队列和锁机制,确保主线程与事件线程间的隔离,并维持事件处理的顺序性。

撰写多线程对象时,执行速度是一项很重要的设计考虑。通常为了加快执行速度,会将执行运作逻辑的主线程,跟发出事件的事件线程做隔离设计。这样的隔离设计可以不让主线程,因为外部事件处理而停顿。而这样的设计下,为了简化线程管理,可以采用ThreadPool来完成事件线程的工作。简单的程序范例如下:

 

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var obj = new ClassA();
            obj.NotifyArrived += new Action<int>(obj_NotifyArrived);
            obj.Start();
            Console.ReadLine();
            obj.Stop();
        }

        static void obj_NotifyArrived(int data)
        {
            Console.WriteLine(data);
        }
    }

    public class ClassA
    {
        // Fields
        private bool _isRunning = true;


        // Methods    
        public void Start()
        {
            Thread thread = new Thread(this.Run);
            thread.Start();
        }

        public void Stop()
        {
            _isRunning = false;
        }

        private void Run()
        {
            int i = 0;
            while (_isRunning == true)
            {
                Thread.Sleep(100);
                this.OnNotifyArrived(i++);
            }
        }


        // Events
        public event System.Action<int> NotifyArrived;
        private void OnNotifyArrived(int data)
        {
            WaitCallback handlerDelegate = delegate(object state)
            {
                var handler = this.NotifyArrived;
                if (handler != null)
                {
                    handler(data);
                }
            };
            ThreadPool.QueueUserWorkItem(handlerDelegate);
        }
    }
}

 

但是这样的隔离设计,却无法满足「必须按照先来后到去处理事件」这样的行为要求。因为ThreadPool只是单纯的为每一个WaitCallback委派,分派一条线程去做处理,而每条线程之间并没有设定执行先后顺序的能力。

 

这个问题困扰了我几天,后来想到一个解法。在主线程跟事件线程之间,垫一层Queue做隔离,将要执行的WaitCallback委派都存放进这个Queue。并且通过Lock的机制,强迫一次只能有一个线程去处理Queue里面的WaitCallback委派。透过这样的设计,就可以完成将执行运作逻辑的主线程,跟发出事件的事件线程做隔离设计的工作。范例程序代码如下:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var obj = new ClassB();
            obj.NotifyArrived += new Action<int>(obj_NotifyArrived);
            obj.Start();
            Console.ReadLine();
            obj.Stop();
        }

        static void obj_NotifyArrived(int data)
        {
            Console.WriteLine(data);
        }
    }

    public class ClassB
    {
        // Fields
        private bool _isRunning = true;

        private readonly object _eventSyncRoot = new object();

        private readonly Queue<WaitCallback> _eventDelegateQueue = new Queue<WaitCallback>();


        // Methods    
        public void Start()
        {
            Thread thread = new Thread(this.Run);
            thread.Start();
        }

        public void Stop()
        {
            _isRunning = false;
        }

        private void Run()
        {
            int i = 0;
            while (_isRunning == true)
            {
                Thread.Sleep(100);
                this.OnNotifyArrived(i++);
            }
        }


        // Events
        public event System.Action<int> NotifyArrived;
        private void OnNotifyArrived(int data)
        {
            // Queue EventDelegate
            WaitCallback eventDelegate = delegate(object state)
            {
                var handler = this.NotifyArrived;
                if (handler != null)
                {
                    handler(data);
                }
            };

            lock (_eventDelegateQueue)
            {
                _eventDelegateQueue.Enqueue(eventDelegate);
            }

            // Run EventDelegate
            WaitCallback handlerDelegate = delegate(object state)
            {
                lock (_eventSyncRoot)
                {
                    WaitCallback runEventDelegate = null;
                    lock (_eventDelegateQueue)
                    {
                        if (_eventDelegateQueue.Count > 0)
                        {
                            runEventDelegate = _eventDelegateQueue.Dequeue();
                        }
                    }

                    if (runEventDelegate != null)
                    {
                        runEventDelegate(null);
                    }
                }
            };
            ThreadPool.QueueUserWorkItem(handlerDelegate);
        }
    }
}

 

最后说一下,要完成这样的隔离设计。不使用ThreadPool,而改用一个独立Thread去处理WaitCallback委派,也是可行的设计。只不过独立一个线程去处理,就需要额外增加管理这个独立线程的工作,这就看每个人的选择跟考虑了。

 

转载于:https://www.cnblogs.com/clark159/archive/2012/03/22/2411438.html

标题基于SpringBoot的马术俱乐部管理系统设计与实现AI更换标题第1章引言介绍马术俱乐部管理系统的研究背景、意义、国内外研究现状、论文方法及创新点。1.1研究背景与意义阐述马术俱乐部管理系统对提升俱乐部管理效率的重要性。1.2国内外研究现状分析国内外马术俱乐部管理系统的发展现状及存在的问题。1.3研究方法以及创新点概述本文采用的研究方法,包括SpringBoot框架的应用,以及系统的创新点。第2章相关理论总结和评述与马术俱乐部管理系统相关的现有理论。2.1SpringBoot框架理论介绍SpringBoot框架的基本原理、特点及其在Web开发中的应用。2.2数据库设计理论阐述数据库设计的基本原则、方法以及在管理系统中的应用。2.3马术俱乐部管理理论概述马术俱乐部管理的基本理论,包括会员管理、课程安排等。第3章系统设计详细描述马术俱乐部管理系统的设计方案,包括架构设计、功能模块设计等。3.1系统架构设计给出系统的整体架构,包括前端、后端和数据库的交互方式。3.2功能模块设计详细介绍系统的各个功能模块,如会员管理、课程管理、预约管理等。3.3数据库设计阐述数据库的设计方案,包括表结构、字段设计以及数据关系。第4章系统实现介绍马术俱乐部管理系统的实现过程,包括开发环境、编码实现等。4.1开发环境搭建介绍系统开发所需的环境,包括操作系统、开发工具等。4.2编码实现详细介绍系统各个功能模块的编码实现过程。4.3系统测试与调试阐述系统的测试方法、测试用例以及调试过程。第5章系统应用与分析呈现马术俱乐部管理系统的应用效果,并进行性能分析。5.1系统应用情况介绍系统在马术俱乐部中的实际应用情况。5.2系统性能分析从响应时间、并发处理能力等方面对系统性能进行分析。5.3用户反馈与改进收集用户反馈,提出系统改进建议。第6章结论与展望总结马术俱乐部管理系统的设计与实现成果,并展望未来的研究
在VB.NET中,`Thread.Join()` 方法用于阻塞当前线程的执行,直到指定的 `Thread` 对象终止运行。这意味着如果你有一个后台任务在一个单独的线程上运行,并且你想等待这个任务完成之后再继续主程序的流程,你可以使用 `Join()`。 以下是关于如何使用 `Thread.Join()` 的详细介绍: ### 简单示例 ```vb Imports System.Threading Module Module1 Sub Main() Dim t As New Thread(AddressOf MyTask) t.Start() Console.WriteLine("主线程正在做其他工作...") ' 主线程将在这里被挂起,直至t线程结束。 t.Join() Console.WriteLine("子线程已完成") End Sub Private Sub MyTask() For i As Integer = 0 To 5 Console.WriteLine($"子线程正在进行 {i}") Threading.Thread.Sleep(1000) ' 模拟耗时操作 Next End Sub End Module ``` 在这个例子中,当我们在控制台看到“主线程正在做其他工作...”的消息后,紧接着会看到从 "MyTask" 函数打印出的信息,最后才会显示 “子线程已完成”。 ### 使用超时时间 有时我们并不想无限期地等下去;我们可以给 `Join()` 提供一个最大等待毫秒数作为参数。如果在这段时间内目标线程还没有结束,则方法返回False值而不会阻止当前线程进一步执行。 ```vb If Not thd.Join(millisecondsTimeout:=2000) Then Console.WriteLine("线程未在此时间内完成") Else Console.WriteLine("线程已成功完成") End If ``` 通过这种方式可以避免程序无响应的问题发生。 ### 相关API说明 - **Thread.Abort():** 虽然可以在某些场景下强制停止另一个线程,但它已经被标记为过时并强烈建议不要直接调用它来中断线程。(推荐的方式是在适当位置检查取消令牌) - **Thread.Interrupt():** 向处于WaitSleepJoin状态下的线程发出信号使其抛出异常提前退出休眠状态 - **CancellationToken:** 更现代的做法是利用 .NET 中提供的协程式编程模型如 Task 和 async/await 来管理异步操作以及支持协作性的取消机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值