Tôi đang sử dụng lớp WeakEventManager<TEventSource, TEventArgs>
để đăng ký các sự kiện trong C#. Đăng ký sự kiện hoạt động tốt, tuy nhiên gọi WeakEventManager<TEventSource, TEventArgs>.RemoveHandler
từ một Task
không phải lúc nào cũng xóa trình xử lý - phần lớn (nhưng không phải tất cả) trong khoảng thời gian trình xử lý vẫn được thực hiện khi sự kiện kích hoạt.WeakEventManager RemoveHandler không phải lúc nào cũng hoạt động khi được gọi không đồng bộ
Điều này được minh họa trong ví dụ sau.
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;
}
}
Trình xử lý được gỡ bỏ mọi lúc, tuy nhiên trong hầu hết các trường hợp, sự kiện vẫn được xử lý.
Tôi có mắc lỗi theo cách mà các phương pháp này được gọi không? Những phương thức này có hỗ trợ được gọi là không đồng bộ không? Có cách tiếp cận thay thế nào có hiệu quả không?
Rất cám ơn sự giúp đỡ của bạn trước.
Cảm ơn, điều đó giải thích lý do tôi thấy hành vi này. Làm thế nào tôi sẽ thay đổi cách tôi gọi Add/RemoveHandler để xử lý được loại bỏ trên cùng một thread? – mickeyt
Sử dụng 'Application.Current.Dispatcher' để gọi các phương thức' AddHandler' và 'RemoveHandler'. –
Không có 'Application.Current' trong ví dụ này. Cảm ơn bạn đã tip về 'DispatcherObject' mặc dù - rất hữu ích! – mickeyt