Pide ayuda nuevamente al maestro de C#
Los eventos son un concepto muy importante. Nuestros programas activan y reciben varios eventos todo el tiempo: eventos de clic del mouse, eventos del teclado y procesamiento de varios eventos del sistema operativo. El llamado evento es un mensaje enviado por un objeto. Por ejemplo, el usuario presiona un botón, un archivo cambia y los datos llegan al socket. El objeto que desencadena el evento se llama remitente y el objeto que captura el evento y responde se llama receptor. Un evento puede tener varios receptores.
En el mecanismo asincrónico, los eventos son una forma muy común de comunicación entre subprocesos. Por ejemplo: el usuario presiona un botón en la interfaz para realizar una tarea que requiere mucho tiempo. El programa ahora inicia un hilo para manejar la tarea y se muestra una barra de progreso en la interfaz de usuario para indicar el estado de ejecución de la tarea del usuario. Esta función se puede procesar mediante eventos. La clase que maneja la tarea se puede utilizar como remitente del mensaje. Cuando se inicia la tarea, se emite el evento "TaskStart" y el evento "TaskDoing" se emite en diferentes momentos durante la tarea y lleva parámetros para indicar la proporción de. la tarea. Cuando finaliza la tarea, se emite el evento "TaskDone", recibe y procesa estos eventos en la pantalla. De esta forma se realiza la función y el grado de acoplamiento entre la interfaz y el módulo que realiza tareas en segundo plano también es mínimo.
Específicamente hablando del lenguaje C#, la implementación de eventos se basa en el concepto de "delegado".
Delegate (delegar)
Delegate es un tipo en C#. En realidad, es una clase que puede contener una referencia a un método. A diferencia de otras clases, una clase delegada puede tener una firma y solo puede contener referencias a métodos que coincidan con su firma. Las funciones que implementa son muy similares a los punteros de función en C/C. Le permite pasar un método m de clase A a otro objeto de clase B, de modo que el objeto de clase B pueda llamar a este método m. Pero en comparación con los punteros de función, los delegados tienen muchas ventajas que los punteros de función no tienen. En primer lugar, los punteros de función solo pueden apuntar a funciones estáticas, mientras que los delegados pueden hacer referencia tanto a funciones estáticas como a funciones miembro no estáticas. Cuando se hace referencia a una función miembro no estática, el delegado no solo guarda una referencia al puntero de entrada de la función, sino que también guarda una referencia a la instancia de clase que llama a esta función. En segundo lugar, en comparación con los punteros de función, los delegados son objetos administrados confiables, seguros y orientados a objetos. En otras palabras, el tiempo de ejecución puede garantizar que el delegado apunte a un método válido y usted no tiene que preocuparse de que el delegado apunte a una dirección no válida o fuera de los límites.
Es muy sencillo implementar un delegado. Puede implementar un delegado mediante los siguientes tres pasos:
1. Declare un objeto delegado que tenga los mismos tipos de parámetros y valores de retorno que el método que desea pasar.
2. Cree el objeto delegado y pase la función que desea pasar como parámetro.
3. Cuando desee implementar llamadas asincrónicas, llame al método a través del objeto creado en el paso anterior.
El siguiente es un ejemplo simple:
clase pública MyDelegateTest
{
// Paso 1, declara el objeto delegado p >
public delegado void MyDelegate(string name);
// Este es el método que queremos pasar, tiene los mismos parámetros y tipo de valor de retorno que MyDelegate
public static void MyDelegateFunc(nombre de cadena)
{
Console.WriteLine("Hola, {0}", nombre
}
);public static void Main ()
{
// Paso 2, crear un objeto delegado
MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);
p>// Paso 3, llamar al delegado
md("sam1111");
}
}
Salida El resultado es: Hola, sam1111
Echemos un vistazo a cómo se manejan los eventos:
Manejo de eventos en C#
Manejo de eventos en C# en realidad es un delegado con una firma especial, como la siguiente:
delegado público void MyEventHandler(objeto remitente, MyEventArgs e);
Dos de los parámetros, el remitente representa el envío de eventos O , e es la clase de parámetro del evento. La clase MyEventArgs se utiliza para contener datos relacionados con eventos. Todas las clases de parámetros de eventos deben derivarse de la clase System.EventArgs. Por supuesto, si su evento no contiene parámetros, puede usar directamente la clase System.EventArgs como parámetros.
Es así de simple. Combinado con la implementación de delegado, podemos resumir la implementación de eventos personalizados en los siguientes pasos:
1. Defina el tipo de objeto delegado, que tiene dos parámetros. El primer parámetro es el objeto emisor del evento y el segundo parámetro es el objeto de clase del parámetro del evento.
2. Defina la clase de parámetro de evento, que debe derivarse de la clase System.EventArgs. Si el evento no requiere parámetros, este paso se puede omitir.
3. Defina el método de manejo de eventos, que debe tener los mismos tipos de parámetros y valores de retorno que el objeto delegado.
4. Utilice la palabra clave event para definir un objeto de evento, que también es un objeto delegado.
5. Utilice el operador = para agregar eventos a la cola de eventos (el operador -= puede eliminar eventos de la cola).
6. Escriba el método de activación del evento llamando al delegado donde se debe activar el evento. En términos generales, este método debe tener restricciones de acceso protegidas y no puede llamarse en público, pero puede ser heredado por subclases. El nombre es OnEventName.
7. Llame al método de activación de eventos en el lugar apropiado para activar el evento.
El siguiente es un ejemplo simple:
usando System;
clase pública EventTest
{
/ / Paso 1, definir el objeto delegado
public delegado void MyEventHandler(object sender, System.EventArgs e);
// Paso 2 omitido
clase pública MyEventCls
{
// Paso 3, defina el método de procesamiento de eventos, que tiene los mismos parámetros y tipo de valor de retorno que el objeto delegado // tipo
public void MyEventFunc (remitente del objeto, System.EventArgs e)
{
Console.WriteLine("¡Mi evento está bien!");
} p>
}
// Paso 4, use la palabra clave event para definir el objeto del evento
private event MyEventHandler myevent
private MyEventCls myecls;
public EventTest()
{
myecls = new MyEventCls();
// Paso 5, use el operador = para agregar eventos a la cola
this.myevent = new MyEventHandler(myecls.MyEventFunc);
}
// Paso 6, escriba la función de activación de eventos llamando delegado
p>protected void OnMyEvent(System.EventArgs e)
{
if(myevent != null)
myevent( esto, e);
}
public void RaiseEvent()
{
EventArgs e = new EventArgs(); p>
// Paso 7, desencadenar evento
OnMyEvent(e);
}
public static void Main()
{
p>
EventTest y = new EventTest();
Console.Write("Ingrese 'a': "); > cadena s = Contras
ole.ReadLine();
if(s == "a")
{
et.RaiseEvent();
}
else
{
Console.WriteLine("Error");
}
}
}
Los resultados de salida son los siguientes, la negrita es la entrada del usuario:
Ingrese 'a': a
Mi ¡El evento está bien!
//////////////////////////////////////// ////// ///////////////////////////////////////////// ////////// //////////////////////////////////////// //////
Los delegados de C# y la activación de eventos
Los delegados son un concepto relativamente complejo en C#. Los delegados en C# son muy similares a los punteros de función en C/C. se puede usar para hacer referencia a los métodos internos del delegado. Encapsularlo y luego usar el método que representa la metareferencia a través de él.
Tiene la característica de que no necesita saber a qué clase de objeto pertenece el método referenciado siempre que el número de parámetros y el tipo de retorno de la función sean consistentes con el metaobjeto representativo.
Puede ser un poco abstracto decir esto. A continuación daré algunos ejemplos simples, con la esperanza de brindarles a los principiantes una comprensión básica.
//Defina un elemento representativo sin parámetros con un valor de retorno de cadena. El elemento representativo solo puede hacer referencia a un método sin parámetros en el objeto que devuelve una cadena.
delegate string MyDelegate();
clase pública MyClass
{ p>
cadena pública SayHello()
{
return "¡Hola mundo!";
}
}
clase pública TestMyClass
{
public static void Main(string[] args)
{
MiClase myClass1=new MyClass() ;
MyDelegate myDelegate1=new MyDelegate(myClass1.SayHello);
//A continuación se utiliza myDelegate1 en lugar del método SayHello del objeto myClass1
System.Console.WriteLine (myDelegate1());
//El resultado de salida es ¡hola mundo! El efecto es el mismo que llamar a myClass1.SayHello();
}
} p>
Si el elemento representativo solo tiene esta función, no será de mucha utilidad. Otra función muy útil del elemento representativo es definir objetos representativos compuestos. Sólo se pueden combinar elementos representativos del mismo tipo para definir objetos compuestos: elimina un objeto delegado de un objeto delegado compuesto
delegate void MyDelegate(string s);
public. clase MiClase
{ p>
public void SayHello(string who)
{
System.Console.WriteLine( who "¡hola!" );
} p>
public void SayGoodBye(string who)
{
System.Console.WriteLine( who "¡adiós! ");
}
}
clase pública TestMyClass
{
pública estática vacía principal (cadena [] args)
{
MiClase miClase1=nueva MiClase();
MiDelegado miDelegado, miDelegado1;
miDelegado=nuevo MiDelegado (myClass1.SayHello);
myDelegate1=new MyDelegate(myClass1.SayGoodBye);
myDelegate =myDelegate1;
//Llamar a myDeletage de esta manera equivale a llamar a myClass1.SayHello y myClass1.SayGoodBye al mismo tiempo
myDelegate(" love.net " );
//Salida del resultado de la ejecución love.net ¡hola! love.net adiós!
}
}
Controlado por eventos Es una característica importante de las aplicaciones de Windows. El elemento representativo de C# se usa para generar eventos, y los eventos se usan para monitorear los cambios en un componente.
Aquí hay un ejemplo simple
//Definir un proxy de evento (elemento representativo)
public delegado void EventHandler(string str);
//Definir clase de origen de evento
class EventSource p>
{
//Defina el elemento representativo como miembro de la clase de origen del evento
evento público EventHandler Diga;
public void TriggerEvent()
p>{
if(this.Say!=null)
//Debido a que Say es un elemento representativo, la operación real realizado por el método Say se registra en él Decisión de la función de manejo de eventos
Say("¡Se produjo un evento!");
}
}
//Prueba
p>Prueba de clase
{
public static void Main()
{
EventSource aEventSource=new EventSource() ;
//Registra la función del controlador de eventos para MyEvent para mostrar una cadena de caracteres similar a esta.Click =new EventHandler(Button1_OnClick);
aEventSource.Say =new EventHandler(MyEvent);
//Esta es una demostración del proceso de activación de eventos, por lo que utilizamos un programa para activarlo automáticamente
// En una aplicación de interfaz gráfica, el usuario generalmente activa el evento y luego el sistema operativo envía un mensaje y llama a la función del controlador, por lo que los programadores solo necesitan registrar la función del controlador de eventos
//Y escribir el código de la función del controlador de eventos y no necesita preocuparse por nada más
aEventSource.TriggerEvent();
}
//Función de manejo de eventos p>
public static void MyEvent(string str)
{
System.Console.WriteLine (str);
}
}
Un breve análisis del mecanismo de procesamiento de eventos de Visual C#
Autor: Wang Kaiming
Introducción al evento:
Cualquier programador Quien haya realizado desarrollo de interfaz gráfica de usuario conocerá el concepto de eventos. Cuando un usuario utiliza un programa, el usuario debe interactuar con el programa hasta cierto punto.
Por ejemplo, cuando el usuario hace clic en un botón en el formulario, el programa generará un evento de que se hizo clic en el botón y responderá a la operación del usuario a través de la función de manejo de eventos correspondiente. De esta forma, la sensación intuitiva del usuario es que el programa ha realizado las tareas que solicité. Por supuesto, los eventos no se generan necesariamente al interactuar con el usuario. Algunos eventos también se generan internamente en el sistema y se solicita su procesamiento. Por ejemplo, los eventos de reloj son un buen ejemplo. Sin embargo, para introducir el mecanismo de procesamiento de eventos en C# (la expansión a un alcance más amplio es todo el marco .Net), primero debemos comprender un concepto llamado "eliminación".
Delegación en C#:
Delegación, como su nombre indica, significa agente intermediario. Los delegados en C# le permiten pasar un método de un objeto a un objeto de otra clase que puede llamar al método. Puede pasar un método m en la clase A (contenido en un delegado) a una clase B, de modo que la clase B pueda llamar al método m en la clase A. Al mismo tiempo, también puede pasar el método de forma estática o de instancia. Entonces, este concepto es muy similar al concepto en C de llamar a métodos en otras clases con punteros de función como parámetros.
El concepto de delegación se propuso por primera vez en Visual J. Ahora C# también aplica el concepto de delegación. Esto también se puede describir como "préstamo". La delegación en C# se implementa heredando una clase en System.Delegate. Los siguientes son los pasos específicos:
1. Declare un objeto delegado y su forma de parámetro debe ser coherente con la forma de parámetro del método que desea incluir.
2. Defina todos los métodos que desee definir y sus formatos de parámetros deben ser los mismos que los del objeto delegado declarado en el primer paso.
3. Cree un objeto delegado e incluya los métodos deseados en el objeto delegado.
4. Llame a los métodos contenidos en el objeto delegado a través del objeto delegado.
El siguiente código C# muestra cómo utilizar los cuatro pasos anteriores para implementar el mecanismo de delegación:
usar Sistema;
archivo://Paso 1: Declarar un objeto delegado
delegado público void MyDelegate(entrada de cadena);
archivo://Paso 2:: Defina cada método, su forma de parámetro y el objeto delegado declarado en el paso 1 debe ser el mismo
clase MiClase1{
public void delegadoMetodo1(entrada de cadena){
Console.WriteLine(
"Este es delegadoMetodo1 y la entrada al método es {0}",
input);
}
public void choseMethod2(string input){
Console.WriteLine(
"Este es delegadoMethod2 y la entrada al método es {0}",
entrada);
}
}
file://Paso 3: Cree un objeto delegado e incluya el método anterior en él
clase MyClass2{
public MyDelegate createDelegate (){
MiClase1 c2=nueva MiClase1();
MiDelegado d1 = nuevo MiDelegado(c2.delegateMethod1);
MiDelegado d2 = nuevo MiDelegado(c2 .delegateMethod2);
MyDelegate d3 = d1 d2;
devuelve d3;
}
}
file://Paso 4: Llame al método contenido en él a través del objeto delegado
clase MyClass3{
public void callDelegate(MyDelegate d, string input){
d(entrada);
}
}
clase Controlador{
static void Main(string[] args){
MiClase2 c2 = nueva MiClase2();
MiDelegado d = c2.createDelegate();
MiClase3 c3 = nueva MiClase3();
c3.callDelegate(d, "Llamar al delegado");
}
}
Función de manejo de eventos en C#:
La función de manejo de eventos en C# es un objeto delegado con un formulario de parámetro específico, que es el siguiente:
public delegado void MyEventHandler(object sender, MyEventArgs e); El primer parámetro (remitente) especifica.
El objeto que desencadenó el evento. El segundo parámetro (e) contiene algunos datos que se pueden utilizar en la función de manejo de eventos. La clase MyEventArgs anterior se hereda de la clase EventArgs, que es la clase base de algunas clases más utilizadas, como la clase MouseEventArgs, la clase ListChangedEventArgs, etc. Para eventos basados en GUI, puede usar objetos de estas clases más amplias ya definidas para completar el procesamiento. Para aquellos eventos que no están basados en GUI, debe derivar su propia clase de la clase EventArgs y agregar Los datos que se incluirán se pasan a; el objeto delegado. El siguiente es un ejemplo simple:
clase pública MyEventArgs EventArgs{
cadena pública m_myEventArgumentdata;
}
En la función del controlador de eventos , puede hacer referencia al objeto delegado a través de la palabra clave event, el método es el siguiente:
public event MyEventHandler MyEvent
Ahora, crearemos dos clases, a través de estas dos clases; Podemos saber cómo funciona el mecanismo de manejo de eventos de C#. En nuestro ejemplo, la clase A proporcionará la función de procesamiento de eventos, creará el objeto delegado en el paso 3 e incluirá la función de procesamiento de eventos en él. Como se mencionó anteriormente, la forma del parámetro de la función de procesamiento de eventos debe ser consistente con la forma del parámetro de. el objeto delegado consistente. Luego, la clase A pasa el objeto delegado a la clase B. Cuando se activa el evento en la clase B, se llama en consecuencia a la función de procesamiento de eventos en la clase A.
Aquí está el código de muestra:
usando System;
file://Paso 1: declarar el objeto delegado
delegado público void MyHandler1(remitente del objeto, MyEventArgs e) ;
delegado público void MyHandler2(remitente del objeto, MyEventArgs e);
archivo: //Paso 2: Método para crear la función de manejo de eventos
clase A{
public const string m_id="Clase A";
public void OnHandler1(remitente del objeto, MyEventArgs e){
Console.WriteLine("I estoy en OnHandler1 y MyEventArgs es {0}",
e.m_id);
}
public void OnHandler2(remitente del objeto, MyEventArgs e){< /p >
Console.WriteLine("Estoy en OnHandler2 y MyEventArgs es {0}",
e.m_id);
}
file: //Paso 3: cree un objeto delegado, incluya la función de manejo de eventos en él y configure el objeto que activará el evento
public A(B b){
MyHandler1 d1=nuevo MyHandler1 (OnHandler1);
MyHandler2 d2=nuevo MyHandler2(OnHandler2);
b.Event1 =d1;
b.Event2 =d2 ;
}
}
archivo://Paso 4: Llame al método contenido a través del objeto delegado (es decir, active el evento)
clase B {
evento público MyHandler1 Event1;
evento público MyHandler2 Event2;
public void FireEvent1(MyEventArgs e){
if(Evento1 != null){
Evento1(este, e);
}
}
vacío público FireEvent2(MyEventArgs e){
if(Event2 != null){
Event2(this, e);
}
}
}
clase pública MyEventArgs EventArgs{
cadena pública m_id;
}
controlador de clase pública {
public static void Main(){
B b= nuevo B();
A a= nuevo A(b);
MisArgumentosEvent e1= nuevo MisArgsEvent();
MisArgumentosEvent e2=
new MyEventArgs();
e1.m_id ="Argumentos del evento para el evento 1";
e2.m_id ="Argumentos del evento para el evento 2"; b.FireEvent1(e1);
b.FireEvent2(e2);
}
}
Eventos GUI en la función de procesamiento C#. :
El método básico para completar la función de procesamiento de eventos en la GUI no es muy diferente de lo que se presentó anteriormente. A continuación, usaremos el método anterior para completar un programa de ejemplo simple. La clase principal MyForm de este programa de instancia se hereda de la clase Form. Al observar el código completo y las anotaciones relacionadas, puede encontrar que no le declaramos un objeto delegado y nos referimos al objeto delegado a través de la palabra clave event. Esto se debe a que el control GUI ya ha hecho este trabajo por nosotros y su delegado. El objeto es System.EventHandler. Sin embargo, todavía tenemos que definir métodos para cada control (es decir, controladores de eventos) e incluirlos en el objeto delegado creado (System.EventHandler). De esa forma, cuando el usuario interactúe con el programa, se activará el controlador de eventos correspondiente.
El código específico es el siguiente:
usando System
usando System.Drawing
usando System.Collections
usando System; .ComponentModel;
usando System.Windows.Forms;
usando System.Data;
formulario MyForm de clase pública{
botón privado m_nameButton;
Botón privado m_clearButton;
Etiqueta privada m_nameLabel;
Contenedor privado m_components = null;
MyForm público(){
initializeComponents();
}
private void inicializeComponents(){
m_nameLabel=new Label();
m_nameButton = nuevo Botón();
m_clearButton = nuevo Botón();
SuspendLayout();
m_nameLabel.Location=nuevo Punto(16, 16);
m_nameLabel.Text="Haga clic en el botón NOMBRE, por favor";
m_nameLabel.Size=new Size(300, 23);
m_nameButton. Ubicación=nuevo Punto(16, 120);
m_nameButton.Size=nuevo Tamaño(176, 23);
m_nameButton.Text="NOMBRE"; >file: //Crea un objeto delegado, incluye métodos y asigna el objeto delegado al evento Click del botón
m_nameButton.Click = new System.EventHandler(NameButtonClicked);
m_clearButton.Location=nuevo Punto (16, 152);
m_clearButton.Size=nuevo Tamaño(176, 23);
m_clearButton.Text="CLEAR";
archivo:/ /Crea un objeto delegado, contiene métodos y asigna el objeto delegado al evento Click del botón
m_clearButton.Click = new System.EventHandler(ClearButtonClicked);
this.ClientSize = nuevo Tamaño( 292, 271);
this.Controls.AddRange(nuevo Control[] {m_nameLabel,
m_nameButton,
m_clearButton}
this.ResumeLayout(false);
}
file: //Definir método (función de procesamiento de eventos), su forma de parámetro debe ser consistente con la del objeto delegado
private void NameButtonClicked(object sender, EventArgs e){
m_nameLabel .Text =
"Mi nombre es John, haga clic en el botón BORRAR para borrarlo";
}
private void ClearButtonClicked(objeto remitente, EventArgs e) {
m_nameLabel.Text="Haga clic en el botón NOMBRE, por favor";
}
public static void Main(){
Aplicación .Run (new MyForm());
}
}
Resumen:
De esta manera, te di un preliminar Introducción al mecanismo de manejo de eventos de C#. A través de este artículo, espero que todos puedan tener una comprensión general del mecanismo de procesamiento de eventos en C# e incluso del mecanismo de procesamiento de eventos de todo el marco .Net. También espero que todos puedan aclarar el concepto más nuevo de "delegación". Finalmente, cabe señalar que si está desarrollando utilizando el entorno de desarrollo integrado de Visual Studio, cada control GUI generará automáticamente una gran cantidad de código relacionado para usted, pero conocer su mecanismo de trabajo interno siempre será de gran ayuda. , ¿bien?