C # multithreading (6): notificación de subproceso

Para revisar, aprendimos bloqueos de subprocesos en las secciones de bloqueo y monitor, sincronización de procesos en la sección Mutex y restricciones del grupo de recursos en la sección Semaphor.

Este artículo aprenderá sobre la clase AutoRestEvent en C # para enviar notificaciones de subprocesos.

Clase AutoRestEvent

Se usa para enviar notificaciones de un hilo a otro.

El documento de Microsoft lo describe de esta manera: significa que el evento de sincronización de subprocesos se restablece automáticamente cuando se recibe una señal después de que se libera un subproceso en espera.

Solo hay un constructor:

Los parámetros en el constructor se utilizan para establecer el estado de la señal.

Constructor Explicación
AutoResetEvent (Boolean) Inicializa una nueva instancia de la clase AutoResetEvent con un valor booleano que indica si se debe establecer el estado inicial en la terminación.

Qué terrible traducción automática.

Métodos comunes

¿Qué es la clase AutoRestEvent y cuáles son los parámetros del constructor? No se preocupe, echemos un vistazo a los métodos de uso común de esta clase:

Método Explicación
Cerrar() Libere todos los recursos ocupados por el WaitHandle actual.
Reiniciar() Establezca el estado del evento como no terminado, lo que hace que el subproceso se bloquee.
Conjunto() Establezca el estado del evento en señalizado, permitiendo que uno o más hilos en espera continúen la ejecución.
WaitOne () Bloquee el hilo actual hasta que el WaitHandle actual reciba la señal.
WaitOne (Int32) Bloquee el hilo actual hasta que el WaitHandle actual reciba una señal, y use un entero con signo de 32 bits para especificar el intervalo de tiempo (en milisegundos).
WaitOne (Int32, Boolean) Bloquee el subproceso actual hasta que el WaitHandle actual reciba una señal y use un entero con signo de 32 bits para especificar el intervalo de tiempo y especificar si debe salir del dominio de sincronización antes de esperar.
WaitOne (TimeSpan) Bloquee el hilo actual hasta que la instancia actual reciba una señal y use TimeSpan para especificar el intervalo de tiempo.
WaitOne (TimeSpan, Boolean) Bloquee el subproceso actual hasta que la instancia actual reciba una señal, use TimeSpan para especificar el intervalo de tiempo y especifique si desea salir del dominio de sincronización antes de esperar.

Un simple ejemplo

Aquí escribimos un programa como este:

Cree un hilo que pueda realizar tareas en múltiples fases; cada vez que complete una fase, debe detenerse y esperar la notificación del hilo secundario antes de continuar con el siguiente paso.

.WaitOne() Se usa para esperar a que otro hilo envíe una notificación;

.Set()Para notificar a un hilo, este caso AutoResetEventse convierte en una condición de terminación;

.ReSet()Se utiliza para restablecer el AutoResetEventestado;

    class Program
    {
        // 线程通知
        private static AutoResetEvent resetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            // 创建线程
            new Thread(DoOne).Start();

            // 用于不断向另一个线程发送信号
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // 发生通知,设置终止状态
            }
        }

        public static void DoOne()
        {
            Console.WriteLine("等待中,请发出信号允许我运行");

            // 等待其它线程发送信号
            resetEvent.WaitOne();

            Console.WriteLine("\n     收到信号,继续执行");
            for (int i = 0; i < 5; i++) Thread.Sleep(TimeSpan.FromSeconds(0.5));

            resetEvent.Reset(); // 重置为非终止状态
            Console.WriteLine("\n第一阶段运行完毕,请继续给予指示");

            // 等待其它线程发送信号
            resetEvent.WaitOne();
            Console.WriteLine("\n     收到信号,继续执行");
            for (int i = 0; i < 5; i++) Thread.Sleep(TimeSpan.FromSeconds(0.5));

            Console.WriteLine("\n第二阶段运行完毕,线程结束,请手动关闭窗口");
        }
    }

Explicar

El objeto AutoResetEvent tiene un estado de terminación y no terminación. Set()Establezca el estado de terminación y Reset()restablezca el estado de no terminación.

Este estado de terminación puede entenderse cuando la señal ha sido notificada; el estado de no terminación es que la señal no ha sido notificada.

Tenga en cuenta que el estado de terminación y el estado de no terminación se refieren al estado de AutoResetEvent, no al estado del subproceso.

El hilo espera la señal llamando al método WaitOne ();
otro hilo puede llamar a Set () para notificar a AutoResetEvent para liberar el hilo en espera.
Entonces AutoResetEvent se convierte en el estado de terminación.

Tenga en cuenta que, si AutoResetEvent ya en el estado final, entonces las llamadas de hilo WaitOne()no va a funcionar. A menos que se llame Reset().

Los parámetros en el constructor establecen este estado. verdadero representa el estado de terminación, falso representa el estado de no terminación. Si se usa new AutoResetEvent(true);, el hilo no necesita esperar la señal al principio.

Después de usar el tipo, usted debe dirigir o tipo de liberación indirecta, llamada explícita Close()/Dispose()o uso using. Por supuesto, también puede salir del programa directamente.

Tenga en cuenta que, si hay varias llamadas Set()intervalo de tiempo es demasiado corto, si la primera Set()no ha terminado todavía (transmisión de la señal requiere un tiempo de procesamiento), entonces el segundo Set()no sea válido (no funciona).

Un ejemplo mas complicado

Diseñamos un programa:

  • Dos hilos comenzaron a ser bloqueados;
  • El subproceso uno puede configurar el subproceso dos para continuar ejecutándose y luego bloquearse;
  • Thread Two puede configurar One para que continúe ejecutándose y luego bloquearse;

El código del programa es el siguiente (después de ejecutar, configure el teclado en el estado de entrada en inglés y luego presione la tecla):

    class Program
    {
        // 控制第一个线程
        // 第一个线程开始时,AutoResetEvent 处于终止状态,无需等待信号
        private static AutoResetEvent oneResetEvent = new AutoResetEvent(true);

        // 控制第二个线程
        // 第二个线程开始时,AutoResetEvent 处于非终止状态,需要等待信号
        private static AutoResetEvent twoResetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            new Thread(DoOne).Start();
            new Thread(DoTwo).Start();

            Console.ReadKey();
        }

        public static void DoOne()
        {
            while (true)
            {
                Console.WriteLine("\n① 按一下键,我就让DoTwo运行");
                Console.ReadKey();
                twoResetEvent.Set();
                oneResetEvent.Reset();
                // 等待 DoTwo() 给我信号
                oneResetEvent.WaitOne();

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("\n     DoOne() 执行");
                Console.ForegroundColor = ConsoleColor.White;
            }
        }

        public static void DoTwo()
        {
            while (true)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1));

                // 等待 DoOne() 给我信号
                twoResetEvent.WaitOne();

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("\n     DoTwo() 执行");
                Console.ForegroundColor = ConsoleColor.White;

                Console.WriteLine("\n② 按一下键,我就让DoOne运行");
                Console.ReadKey();
                oneResetEvent.Set();
                twoResetEvent.Reset();
            }
        }
    }

Explicar

Las funciones que tienen dos hilos: bloquearse a sí mismos y desbloquear otro hilo.

Utilice una imagen de la película "Mejor socio" para comprender.

DoOne y DoTwo se turnan para respirar. No pueden controlar su propia respiración, pero pueden decidir respirar.

Me follas, te follo, se pueden respirar.

Por supuesto, WaitOne()también puede establecer el tiempo de espera. Si DoOne no permite que DoTwo respire, después de esperar un cierto tiempo, Vajra puede forzar el equilibrio y respirar en el piso.

Tenga en cuenta que el uso incorrecto de AutoRestEvent es propenso a un punto muerto.
Además, AutoRestEvent utiliza el modo de tiempo del núcleo, por lo que el tiempo de espera no puede ser demasiado largo, de lo contrario consumirá tiempo de CPU.

AutoResetEvent también es adecuado para la sincronización de subprocesos.

Además, el uso de hilo WaitOne(), otro hilo utilizando la Set()notificación, el objeto restaurará automáticamente el estado AutoResetEvent no terminado, no requiere el uso de hilos Reset().

Supongo que te gusta

Origin www.cnblogs.com/whuanle/p/12730169.html
Recomendado
Clasificación