我正在使用WeakEventManager<TEventSource, TEventArgs>
类来订阅C#中的事件。事件订阅工作正常,但是从Task
调用WeakEventManager<TEventSource, TEventArgs>.RemoveHandler
并不总是删除处理程序 - 当事件触发时处理程序仍然执行的大部分时间(但不是全部)。
以下示例说明了这一点。
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;
}
}
处理程序一直被删除,但在大多数情况下仍会处理事件。
我是否在调用这些方法时出错?这些方法是否支持异步调用?是否有其他方法可行?
非常感谢您的帮助。
答案 0 :(得分:8)
这是因为WeakEventManager
存储在为当前线程(source)初始化的当前WeakEventTable
中:
[ThreadStatic]
private static WeakEventTable _currentTable; // one table per thread
你使用线程池任务sheduler,它是默认的sheduler。它有时会在同一个线程上调用AddHandler
和RemoveHandler
。但有时它会在不同的主题上调用RemoveHandler
,而您有另一个WeakEventManager
没有请求的EventSource
。
注意:如果类型继承自DispatcherObject
,则此类型的实例取决于创建它们的线程。如果DispatcherObject
是单身,则每个线程创建一个。
因此,如果您看到DispatcherObject
,则仅从创建它的线程调用其方法。否则,你会遇到问题。