C#线程调度AutoResetEvent和ManualResetEvent区别

发布时间:2022-07-02 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了C#线程调度AutoResetEvent和ManualResetEvent区别脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

 

共同点:

  均继承 EventWaitHandle 接口,因此,均具有以下功能:

Reset() //红灯

Set() //绿灯

WaITOne() // 等待信号

本质都是阻塞信号模型,就像windows模型

whtle(true)

{

Sleep(1);

sing=true;

}

 

不同点:

AutoResetEvent   收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne 。

ManualResetEvent  收到 Set 后,所有处理 WaitOne 状态线程均继续执行。

 

msdn 提到(如果没有线程 处于WaitOne() 状态,而调用 Set , AutoResetEvent 将保持Set 状态):

调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent 将保持终止状态直到一个等待线程释放,并自动返回到非信号状态。 如果没有线程处于等待状态,状态将无限期地保持已发出信号。

因此通常WatiOne 之前,先 Reset() 一下,清除Set 信号

 

需要注意的是(两个 Set 调用之间时间较短,第二个 Set 信号可能会丢失,因此连续 Set 调用,中间需要 Sleep 一定时间):

不能保证的每个调用Set方法将释放一个线程。 如果两次调用太靠近在一起,以便第二次调用前释放线程发生,只有一个线程被释放。 就像第二次调用未发生。 此外,如果Set时没有等待的线程调用和AutoResetEvent已终止,则调用不起作用。

 

原理上

AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();

 

实际使用过程中,有差别的,如下示例:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testManualResetEvent
{
    class PRogram
    {
        static object objManualResetEvent = new object();
        static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
         //static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
        static void Main(string[] args)
        {
           
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
                t.Start();
            }
            
            manu.Set();
            manu.Reset();

            Console.ReadKey();
        }

        static void Product()
        {
            manu.WaitOne(10000);
            Console.WriteLine(System.Threading.Thread.currentThread.ManagedThreadId);
        }
    }
}

 

实际执行结果 , 在 执行 set 后 reset 前 ,有多少个线程唤起执行,无法预料: 

C#线程调度AutoResetEvent和ManualResetEvent区别

 

需要加锁 ,确保一次通过一个线程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testManualResetEvent
{
    class Program
    {
        static object objManualResetEvent = new object();
        static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
         //static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
        static void Main(string[] args)
        {
           
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
                t.Start();
            }
            
            manu.Set();

            //System.Threading.Thread.Sleep(100); //连续 set 需要 sleep
            //manu.Set();
            //manu.Reset();

            //System.Threading.Thread.Sleep(100);
            //manu.Set();
            //manu.Reset();

            Console.ReadKey();
        }

        static void Product()
        {
            lock (objManualResetEvent)
            {
                manu.WaitOne(10000);          manu.Reset();
                Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
            }
        }
    }
}

共同点:

  均继承 EventWaitHandle 接口,因此,均具有以下功能:

Reset() //红灯

Set() //绿灯

WaitOne() // 等待信号

本质都是阻塞信号模型,就像windows模型

whtle(true)

{

Sleep(1);

sing=true;

}

 

不同点:

AutoResetEvent   收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne 。

ManualResetEvent  收到 Set 后,所有处理 WaitOne 状态线程均继续执行。

 

msdn 提到(如果没有线程 处于WaitOne() 状态,而调用 Set , AutoResetEvent 将保持Set 状态):

调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent 将保持终止状态直到一个等待线程释放,并自动返回到非信号状态。 如果没有线程处于等待状态,状态将无限期地保持已发出信号。

因此通常WatiOne 之前,先 Reset() 一下,清除Set 信号

 

需要注意的是(两个 Set 调用之间时间较短,第二个 Set 信号可能会丢失,因此连续 Set 调用,中间需要 Sleep 一定时间):

不能保证的每个调用Set方法将释放一个线程。 如果两次调用太靠近在一起,以便第二次调用前释放线程发生,只有一个线程被释放。 就像第二次调用未发生。 此外,如果Set时没有等待的线程调用和AutoResetEvent已终止,则调用不起作用。

 

原理上

AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();

 

实际使用过程中,有差别的,如下示例:

 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testManualResetEvent
{
    class Program
    {
        static object objManualResetEvent = new object();
        static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
         //static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
        static void Main(string[] args)
        {
           
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
                t.Start();
            }
            
            manu.Set();
            manu.Reset();

            Console.ReadKey();
        }

        static void Product()
        {
            manu.WaitOne(10000);
            Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
        }
    }
}

 

实际执行结果 , 在 执行 set 后 reset 前 ,有多少个线程唤起执行,无法预料: 

C#线程调度AutoResetEvent和ManualResetEvent区别

 

需要加锁 ,确保一次通过一个线程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testManualResetEvent
{
    class Program
    {
        static object objManualResetEvent = new object();
        static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);
         //static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);
        static void Main(string[] args)
        {
           
            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));
                t.Start();
            }
            
            manu.Set();

            //System.Threading.Thread.Sleep(100); //连续 set 需要 sleep
            //manu.Set();
            //manu.Reset();

            //System.Threading.Thread.Sleep(100);
            //manu.Set();
            //manu.Reset();

            Console.ReadKey();
        }

        static void Product()
        {
            lock (objManualResetEvent)
            {
                manu.WaitOne(10000);          manu.Reset();
                Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
            }
        }
    }
}

脚本宝典总结

以上是脚本宝典为你收集整理的C#线程调度AutoResetEvent和ManualResetEvent区别全部内容,希望文章能够帮你解决C#线程调度AutoResetEvent和ManualResetEvent区别所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。