Sto utilizzando la classe WeakEventManager<TEventSource, TEventArgs>
per iscriversi agli eventi in C#. L'abbonamento all'evento funziona bene, tuttavia chiamare WeakEventManager<TEventSource, TEventArgs>.RemoveHandler
da un Task
non rimuove sempre il gestore - la maggior parte (ma non tutto) del tempo in cui il gestore viene ancora eseguito quando l'evento viene attivato.WeakEventManager RemoveHandler non funziona sempre se chiamato in modo asincrono
Ciò è illustrato nel seguente esempio.
public class EventSource
{
public event EventHandler Fired = delegate { };
public void FireEvent()
{
Fired(this, EventArgs.Empty);
}
}
class Program
{
private static bool added, removed, handled;
static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
{
added = removed = handled = false;
var source = new EventSource();
AddHandlerAsync(source).Wait();
RemoveHandlerAsync(source).Wait();
source.FireEvent();
if (removed && handled) Console.WriteLine("Event handled after removal!");
else Console.WriteLine("----------------------------");
}
Console.ReadKey();
}
private async static Task AddHandlerAsync(EventSource source)
{
await Task.Run(() =>
{
System.Windows.WeakEventManager<EventSource, EventArgs>.AddHandler(source, "Fired", HandleEvent);
added = true;
});
}
private async static Task RemoveHandlerAsync(EventSource source)
{
await Task.Run(() =>
{
System.Windows.WeakEventManager<EventSource, EventArgs>.RemoveHandler(source, "Fired", HandleEvent);
removed = true;
});
}
private static void HandleEvent(object sender, EventArgs e)
{
handled = true;
}
}
Il gestore viene rimosso tutto il tempo, tuttavia nella maggior parte dei casi l'evento viene comunque gestito.
Sto facendo un errore nel modo in cui vengono chiamati questi metodi? Questi metodi supportano l'essere chiamati in modo asincrono? Esiste un approccio alternativo che potrebbe funzionare?
Molte grazie per il vostro aiuto in anticipo.
Grazie, questo spiega perché sto vedendo questo comportamento. Come cambierei il modo in cui sto chiamando Aggiungi/RimuoviHandler in modo che i gestori vengano rimossi sullo stesso thread? – mickeyt
Utilizzare 'Application.Current.Dispatcher' per invocare i metodi' AddHandler' e 'RemoveHandler'. –
In questo esempio non c'è 'Application.Current'. Grazie per il suggerimento su 'DispatcherObject' - molto utile! – mickeyt