标签: weakeventmanager

使用.NET的WeakEventManager实现弱事件的示例

是否有使用.NET的WeakEventManager的弱事件的示例实现?

我正在尝试通过遵循文档中的"Notes to Inheritors"来实现它,但它很模糊.例如,我无法弄清楚如何ProtectedAddListenerAddListener我的自定义管理器中的静态函数调用.

.net weak-events weakeventmanager

25
推荐指数
2
解决办法
1万
查看次数

WeakEventManager和DependencyPropertyChangedEventArgs

我想知道什么是最好的方式使用WeakEventManager(4.5很好)与提供DependencyPropertyChangedEventArgs的事件.这些不是从EventArgs派生的(出于性能原因),因此WeakEventManager无法正常运行.

任何指南,链接或提示将非常感谢!

wpf weakeventmanager .net-4.5

5
推荐指数
1
解决办法
663
查看次数

WeakEventManager保存对订户的引用

我一直在使用WeakEventManager来避免内存泄漏,我开始过度使用它们.我为INotifyPropertyChanged创建了扩展方法,例如:


public static void AddWeakPropertyChanged(this INotifyPropertyChanged item, Action handler)
{
    PropertyChangedEventManager.AddHandler(item, (s, e) => handler(e.PropertyName), string.Empty);
}
Run Code Online (Sandbox Code Playgroud)

现在我很快意识到,这不起作用.实际上,您无法真正使用匿名方法进行弱事件处理.(如果我理解正确,那么编译器为它创建一个'闭包类'(用于保存引用的值),它具有处理程序,但由于你的闭包类没有在任何地方被引用,因此GC将清除它,并且事件处理程序不会被叫)

问题1:这是正确的吗?我的意思是它是正确的,然后当使用匿名方法(或lambda)作为弱事件处理程序时,仅当GC没有同时运行时才调用处理程序(例如,它是不确定的)?

嗯,我非常感谢,所以我做了一些单元测试,以确保我做对了.在我进行以下单元测试之前,它似乎还可以:


        class DidRun
        {
            public bool Value { get; set; }
        }
        class TestEventPublisher
        {
            public event EventHandler<EventArgs> MyEvent;
            public void RaiseMyEvent()
            {
                if (MyEvent != null)
                    MyEvent(this, EventArgs.Empty);

            }
        }
        class TestClosure
        {
            public DidRun didRun { get; set; }
            public EventHandler<EventArgs> Handler { get; private set; }
            public TestClosure()
            {
                this.Handler = new EventHandler<EventArgs>((s, e) => didRun.Value = true); …
Run Code Online (Sandbox Code Playgroud)

c# closures weakeventmanager

5
推荐指数
1
解决办法
1456
查看次数

为什么 WeakEventManager 在发送者不是名义者时不会触发事件?

我不喜欢不合标准的模式,但我正在对我的应用程序进行快速测试,并且遇到了这种奇怪的行为。

考虑一个公开事件的普通类,这里是非常常见的 PropertyChanged,但我认为可以是任何其他类。

订阅者选择通过 WeakEventManager 助手订阅事件。现在,“奇怪”的事情是实际的发件人引用:只要实例与订阅中使用的实例相同,一切都会顺利。但是,当您使用另一个对象时,不会发出通知。

同样,这不是一个好的模式,但我想知道这种限制是否有任何充分的理由,或者说这是一种错误。与其说是真正的需要,不如说是一种好奇心。

class Class1
{
    static void Main(string[] args)
    {
        var c = new MyClass();

        WeakEventManager<INotifyPropertyChanged, PropertyChangedEventArgs>.AddHandler(
            c,
            "PropertyChanged",
            Handler
            );

        c.ActualSender = c;
        c.Number = 123;  //will raise

        c.ActualSender = new Class1();
        c.Number = 456;  //won't raise

        Console.ReadKey();
    }

    static void Handler(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("Handled!");
    }
}

class MyClass : INotifyPropertyChanged
{
    public object ActualSender { get; set; }


    private int _number;
    public int Number
    {
        get { return this._number; …
Run Code Online (Sandbox Code Playgroud)

c# weak-events weakeventmanager

5
推荐指数
1
解决办法
2164
查看次数

WeakEventManager 和 Destructor 的内存保留问题

我遇到了与 WeakEventManager 的使用相关的内存保留问题。使用 DotMemoryProfiler 对我的应用程序进行分析后,我发现每当我使用以下命令添加处理程序时WeakEventManager.AddHandler,都会导致向 ConditionalWeakTable<object, object> 添加一个实例,并且该条目将被保留,除非手动删除该处理程序(即使在析构函数中删除也不会\ xe2\x80\x99t 工作,你必须有一个函数来显式删除它)。

\n

从下面的代码中,您可以看到手动调用 Detach 方法与通过析构函数调用它是有区别的。手动调用时,ConditionalWeakTable 会被正确收集并在 DotMemoryProfiler 快照中标记为“Dead”。然而,当从析构函数 ( ) 调用它时~Subscriber,ConditionalWeakTable 仍然存在。请注意,快照是在执行 Detach 之后拍摄的(因为序列打印在控制台中)。我还确保它在发布模式下运行,并且未选中“抑制 JIT 优化”选项

\n

这是显示幸存对象的 DotMemory 快照的比较:

\n

在此输入图像描述

\n

您可能认为幸存的字节不多\xe2\x80\x99,但这在我们的实际应用程序中引起了问题,因为我们广泛使用 Wea​​kEventManager 并通过析构函数取消订阅它,导致保留大量内存(超过12MB)。\n这是一个示例的屏幕截图,它可以在我们的实际应用程序中保留如此巨大的内存量。

\n

在此输入图像描述

\n

为了提供更多上下文,这里是相关的代码片段:

\n
class Program\n{\n    static void Main()\n    {\n        var isolator = new Action(() => { \n            var publisher = new Publisher();\n            var subscriber = new Subscriber();\n\n            subscriber.Init(publisher);\n            MemoryProfiler.GetSnapshot();\n\n            //subscriber.Detach(publisher); // detach it manually won\'t cause issue\n      });\n            isolator();\n\n …
Run Code Online (Sandbox Code Playgroud)

c# weakeventmanager

5
推荐指数
1
解决办法
318
查看次数

我应该在收听DependencyProperty更改时使用弱事件侦听器吗?

我正在框架中查找WeakEventManager的实现,该实现侦听DependencyProperties的更改.我发现唯一的弱属性更改事件侦听器PropertyChangedEventManager被设计用于实现INotifyPropertyChanged的类型,这让我感到有点困惑.

这是否意味着如果您收听DependencyProperty进行更改

DependencyPropertyDescriptor
    .FromProperty(target, target.OwnerType)
    .AddValueChanged(component, handler)
Run Code Online (Sandbox Code Playgroud)

我不必担心因事件登记而活着的实例泄露?

.net wpf events weak-references weakeventmanager

4
推荐指数
1
解决办法
940
查看次数

WeakEventManager 和静态事件

我正在努力适应WeakEventManager,但我偶然发现了以下内容:



和之间的唯一区别是,请忽略复制/粘贴错误 ;)ABstaticnameof

我找到了关于泛型和静态类型的答案,但我想知道那WeakEventManager在做什么A?不知何故,它可以null作为静态事件的来源。

我在寻找一个简单的答案,为什么static事件是好的,但static class因为TEventSource突然没有。


代码:

public class A
{
    public static event EventHandler Event;
}

public static class B
{
    public static event EventHandler Event;
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        WeakEventManager<A, EventArgs>.AddHandler(null, nameof(A.Event), (s, e) => { });
        WeakEventManager<B, EventArgs>.AddHandler(null, nameof(B.Event), (s, e) => { });
    }
}
Run Code Online (Sandbox Code Playgroud)

错误: …

c# generics weakeventmanager

3
推荐指数
1
解决办法
1009
查看次数

在类型上找不到事件

我有以下例外

WindowsBase.dll 中发生类型为“System.ArgumentException”的未处理异常

附加信息:在“ConsoleApplication.ITest”类型上找不到“事件”事件。

在这个再现中:

using System.Windows; // add reference to WindowsBase

interface IBase
{
    event EventHandler Event;
}

interface ITest : IBase { }

class Test : ITest
{
    public event EventHandler Event;
}

class Program
{
    static void Main(string[] args)
    {
        var test = new Test();
        WeakEventManager<IBase, EventArgs>.AddHandler(test, "Event", (s, e) => { }); // works
        WeakEventManager<ITest, EventArgs>.AddHandler(test, "Event", (s, e) => { }); // exception
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么找不到通过接口事件继承此方法抛出异常。

c# events weakeventmanager

3
推荐指数
1
解决办法
6786
查看次数