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