【问题标题】:Event handling with an anonymous delegate使用匿名委托进行事件处理
【发布时间】:2010-01-27 13:27:20
【问题描述】:

为了记录:我发现了一个类似的问题here,但我必须详细说明一下这个主题。

我的具体情况是这样的:

在 Silverlight 4 中,myFrameworkElement.FindName("otherElementName") 方法现在似乎工作正常,但我遇到了一个问题。当元素显然还没有添加到可视化树时,它仍然返回null

但现在我需要在自定义UserControl 处理程序的DependencyPropertyPropertyChangedCallback 中使用此功能。在此范围内,尚不确定 UserControl 是否已添加到可视化树中。但是我必须对树中的另一个元素执行某个操作。当元素已经可用时,它可以并且应该立即完成。如果没有,则必须在可用时立即完成。所以我想出了这个扩展方法,我可以这样调用:

myFrameworkElement.FindNameEnsured("otherElementName",
    result => this.DoSomethingWith(result));

扩展方法的代码如下:

    static public void FindNameEnsured(this FrameworkElement self,
            string name, Action<object> resultAction)
    {
        if (self != null && resultAction != null)
        {
            object result = self.FindName(name);

            if (result != null)
            {
                resultAction(result);
            }
            else
            {
                RoutedEventHandler handler = null;
                handler = (sender, e) =>
                     {
                         result = self.FindName(name);
                         resultAction(result);

                         self.Loaded -= handler;
                     };

                self.Loaded += handler;
            }
        }

如您所见,我必须使用匿名委托,因为我需要处理程序内部的 nameresultAction 的值。然后我取消订阅处理程序内部的事件,因为我是一个聪明而干净的人并且不希望泄漏。我也不想在这里用一些花哨的 WeakEventFactories 或类似的东西打破任何车轮上的苍蝇。

到目前为止,这工作顺利。但我有一些问题。

  1. 这通常是在处理程序内部取消订阅事件处理程序的一种足够干净的方法吗?还是最终会杀死一只无辜的小狗?
  2. 是否会因为在匿名委托中使用外部范围变量而导致一些问题,例如一些泄漏?
  3. 是否存在线程同步问题导致我“错过”Loaded 事件?在这种特殊情况下,应该只涉及 Silverlight 的 UI 调度程序线程。但如果这仍然是个问题,和/或如果我需要在非 UI 相关的场景中使用类似的功能,那么 f1x0r 的最佳方法是什么?

已经感谢您的耐心和时间阅读我冗长的阐述。 ;-)

【问题讨论】:

    标签: .net events anonymous-delegates


    【解决方案1】:
    1. 应该没问题,虽然有点痛。 LINQ to Rx 有一个更好的取消订阅的想法——当你订阅时,你会得到一个IDisposable,当你处理它时它会取消订阅。但这不适合现有的事件模型。
    2. 我认为在这种特殊情况下您不会有任何泄漏 - 在某些边缘条件下,使用同一范围内的变量的两个不同匿名函数最终都可以捕获它们不需要的变量,但确实如此是一个边缘情况。
    3. 您必须提供有关假设情况的更准确的详细信息 - 您究竟担心什么、事件的实施方式等。

    【讨论】:

    • 好的,谢谢Skeet先生的回答。关于第(3)点,一旦我发现一个场景或者它成为一个紧迫的问题,我会回来或发布一个新问题。 ;-)
    猜你喜欢
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    相关资源
    最近更新 更多