.NET组件程序设计 第8章 多线程和并发管理 同步线程_可等待事件

3.可等待事件(EventWaitHandle)

EventWaitHandle派生自WaitHandle,用于跨线程通知事件。

EventWaitHandle有两种方式:手动重置(ManualReset)和自动重置(AutoReset)对应强类型子类ManualResetEvent和AutoResetEvent。

 

手动重置事件

public class EventDemo : IDisposable
{
    //创建手动重置事件对象
    private ManualResetEvent m_Event;

    //构造函数
    public EventDemo()
    {
        m_Event = new ManualResetEvent(false);

        //启动一个新线程
        Thread thread = new Thread(DoWork);
        thread.Start();
    }

    public void DoWork()
    {
        int counter = 0;
        while (true)
        {
            //阻塞当前线程,直到收到信号
            m_Event.WaitOne();

            counter++;
            Console.WriteLine("编号:" + counter);
        }
    }

    public void GoThread()
    {
        //设置句柄状态为:信号已发
        //一旦信号状态为已发,它就停留在已发状态,直到手动调用Reset()
        //信号已发,所有等待线程被解锁
        m_Event.Set();
        Console.WriteLine("开始!");
    }

    public void StopThread()
    {
        //设置句柄状态为:信号未发
        //阻塞线程
        m_Event.Reset();
        Console.WriteLine("中断!");
    }

    #region IDisposable 成员

    public void Dispose()
    {
        m_Event.Close();
    }

    #endregion
}

//调用
EventDemo ed = new EventDemo();

//在另一线程上调用ed的GoThread()等方法
ed.GoThread();
Thread.Sleep(10);
ed.StopThread();

ed.GoThread();
Thread.Sleep(10);
ed.StopThread();

 

自动重置事件

和手动重置事件基本相同,区别在:自动重置一旦调用Set()后,处于阻塞的线程开始运行,同时在这一刻,状态自动反转为型号未发(无需调用Rest())。如调用Set(),无线程等待,将继续保持信号已发状态。自动重置事件将Set()和Reset()调用结合到一个原子操作中

private AutoResetEvent m_Event;

/* 其他同上 */

//调用
//无需调用StopThread(),完成一原子操作状态自动变为未发信号
ed.GoThread();
Thread.Sleep(10);
ed.GoThread(); 

 

线程集结问题

线程相互等待,然后同时继续执行(并发完成)。

class Rendezvous
{
    //初始化信号为已发送状态(终止状态)
    AutoResetEvent m_First = new AutoResetEvent(true);

    AutoResetEvent m_Event1 = new AutoResetEvent(false);
    AutoResetEvent m_Event2 = new AutoResetEvent(false);

    //在某一点,每个线程调用该方法,
    //最先调用Wait()的线程,最先被阻塞
    //一旦第二个线程调用Wait(),两个线程都自动继续执行任务
    public void Wait()
    {
        //判断线程是否第一个调用
        //如果m_First收到信号(信号已发送状态),则为 true;否则为 false;
        //由于为AutoResetEvent实例,执行完原子操作后,会自动重置事件状态为信号未发状态,因此第二调用的线程返回值始终为false
        bool first = m_First.WaitOne(TimeSpan.Zero, false);

        if (first)
        {
            //给m_Event1发信号并等待m_Event2
            //SignalAndWait使发信号和等待为一元子操作进行,保证两线程,互相等待然后同时继续执行
            WaitHandle.SignalAndWait(m_Event1,m_Event2);
        }
        else
        {
            //给m_Event2发信号并等待m_Event1
            WaitHandle.SignalAndWait(m_Event2, m_Event1);
        }
    }

    public void Reset()
    {
        //重置m_First为信号已发送状态,用于再次集结两个线程
        m_First.Set();
    }
}

class Program
{
    static Rendezvous m_Rend = new Rendezvous();

    public static void ThreadMethod1()
    {
        m_Rend.Wait();

        Console.WriteLine(Thread.CurrentThread.Name);
    }

    public static void ThreadMethod2()
    {
        m_Rend.Wait();

        Console.WriteLine(Thread.CurrentThread.Name );
    }

    static void Main(string[] args)
    {
        //调用
        Thread threadA = new Thread(ThreadMethod1);
        threadA.Name = "threadA";
        threadA.Start();

        Thread threadB = new Thread(ThreadMethod2);
        threadB.Name = "threadB";
        threadB.Start();

        Console.Read();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.NET 中实现多线程并发可以使用以下几种方法: 1. 使用 Thread 类:Thread 类是 .NET 提供的最基本的多线程编程类。你可以创建多个 Thread 实例,并在每个实例中执行不同的任务。但是需要注意线程同步和协作问题,避免出现竞态条件和死锁等问题。 2. 使用 ThreadPool 类:ThreadPool 是一个已经初始化的线程池,可以通过 QueueUserWorkItem 方法将任务加入到线程池中。线程池会自动管理线程的创建和回收,适用于大量短时间执行的任务。 3. 使用 Task Parallel Library(TPL):TPL 是 .NET Framework 4.0 引入的并行编程模型,它提供了更高级的抽象,通过 Task 类封装了多线程操作。你可以使用 Task.Factory.StartNew 方法创建和管理任务,并通过 Task.WaitAll 或 Task.WaitAny 等方法等待任务完成。 4. 使用 async/await 异步编程模型:.NET Framework 4.5 引入了异步编程模型,通过 async/await 关键字可以方便地进行异步操作。你可以使用 Task.Run 方法在后台线程执行耗时操作,同时使用 async/await 简化异步代码的编写。 5. 使用并发集合:.NET 提供了一些并发集合类,如 ConcurrentQueue、ConcurrentStack 和 ConcurrentDictionary 等,它们在多线程环境下提供了安全的并发访问。 在实现多线程并发时,需要注意线程安全、资源共享和线程同步等问题,避免出现数据竞争和死锁等并发问题。可以使用锁、互斥量、信号量、事件同步机制来保证线程安全和协作。同时,合理地使用线程池、任务调度和异步编程等技术可以提高并发性能和资源利用率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值