c# - tiempo - visual basic timer interval
C#agregar y eliminar eventos de un temporizador (7)
Al agregar y eliminar manejadores de eventos, está creando un nuevo contenedor para su delegado cada vez. Por lo tanto, en su método de eliminación, está intentando eliminar un nuevo objeto EventHandler que nunca se agregó como escucha al evento en primer lugar.
Si desea seguir utilizando este tipo de configuración, tal vez pueda colocar sus manejadores de eventos en un diccionario. En el método addEvent, inserte su EventHandler recién creado en su diccionario, y en el método removeEvent, extraiga el EventHandler del diccionario y elimínelo en lugar de crear uno nuevo.
Estoy tratando de agregar y eliminar eventos de un temporizador y tengo el siguiente código:
Timer myTimer = new Timer(); // Windows.Forms Timer
public void addEvent(MyDelegate ev)
{
myTimer.Tick += new EventHandler(ev);
}
public void removeEvent(MyDelegate ev)
{
myTimer.Tick -= new EventHandler(ev);
}
No sé Si estoy haciendo algo estúpido al tratar de agregar y eliminar delegados de esta manera, puedo agregar delegados y hacer que disparen como se esperaba. Sin embargo, cuando intento eliminar los eventos, continúan activando Timers Tick.
¿Alguien puede ver algo obviamente mal?
Deberías poder anular la suscripción haciendo referencia al nombre de tu método de manejo par así:
public void removeEvent(MyDelegate ev)
{
myTimer.Tick -= ev as EventHandler;
}
El código inicial funciona bien, siempre que MyDelegate
'' ev
'' pase a addEvent
y removeEvent
sea la misma instancia de objeto (por ejemplo, si hay un campo MyDelegate
nivel de MyDelegate
que contiene la instancia o si sigue los consejos de varios otros aquí y mantenga el objeto (s) MyDelegate
en un diccionario).
Sospecho que el problema es que el código que llama a addEvent
y removeEvent
está pasando nuevas instancias de MyDelegate
apuntando a algún método del manejador, así:
addEvent(new MyDelegate(this.HandlerMethod));
// ... do some stuff
removeEvent(new MyDelegate(this.HandlerMethod));
En este caso, addEvent
y removeEvent
están creando delegados de EventHandler
que apuntan a diferentes direcciones de método, aunque esos delegados a su vez están apuntando al mismo método ( this.HandlerMethod
). Esto se debe a que los delegados de EventHandler
add
y remove
punto de creación al método MyDelegate.Invoke()
en diferentes instancias de MyDelegate
lugar de directamente a la dirección de this.HandlerMethod
.
No sé lo que está haciendo mal, pero el enfoque habitual que utilizaría para los temporizadores sería suscribirse al evento Tick
, y luego desactivar el temporizador cuando no desea recibir los eventos, volver a habilitar cuando tú lo haces.
Puede que no lo ayude si tiene más de un controlador de eventos conectado al evento, pero con algo de suerte.
Tu problema proviene de tener métodos de ayuda para hacer esto. Sin ellos, funciona como se esperaba, con ellos no sabe qué desenganchar.
Para solucionar esto, necesitará mantener un diccionario con el valor que es el manejador de eventos creado en el método de enganche para que pueda eliminar ese valor más adelante.
Algo como:
var handlers = new Dictionary<MyDelegate, EventHandler>();
public void addEvent(MyDelegate ev)
{
var handler = new EventHandler(ev);
handlers.Add(ev, handler);
myTimer.Tick += handler;
}
public void removeEvent(MyDelegate ev)
{
myTimer.Tick -= handlers[ev];
}
Debe agregar las comprobaciones apropiadas si el elemento existe.
También podría cambiar su tipo de parámetro y funcionará como se espera.
public void addEvent(EventHandler ev)
{
myTimer.Tick += ev;
}
public void removeEvent(EventHandler ev)
{
myTimer.Tick -= ev;
}
addEvent(new EventHandler(...));
removeEvent(new EventHandler(...));
Yo creo que este código:
myTimer.Tick -= new EventHandler(ev);
crea un nuevo objeto EventHandler. Nunca eliminará un EventHandler existente. Para obtener la funcionalidad que desea, debe pasar a EventHandlers, no a MyDelegates, los métodos para agregar y eliminar:
Timer myTimer = new Timer(); // Windows.Forms Timer
public void addEvent(EventHandler ev)
{
myTimer.Tick += ev;
}
public void removeEvent(EventHandler ev)
{
myTimer.Tick -= ev;
}
El código de llamada tendrá que hacer un seguimiento de los EventHandlers agregados, para que pueda pasar en el mismo objeto EventHandler cuando sea el momento de darse de baja.
Esto debería funcionar:
private void timer_Tick(object sender, EventArgs e)
{
try
{
// Disallow re-entry
timer.Tick -= timer_Tick;
. . .
}
finally
{
timer.Tick += timer_Tick;
}
}