代码之家  ›  专栏  ›  技术社区  ›  herzmeister

使用匿名委托处理事件

  •  0
  • herzmeister  · 技术社区  · 14 年前

    我发现了一个类似的问题 here 但我必须在这个问题上再详细阐述一点。

    我的具体设想是:

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

    但现在我需要在 DependencyProperty PropertyChangedCallback 风俗习惯 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;
                }
            }
    

    如您所见,我必须使用匿名委托,因为我需要 name resultAction 处理程序内部。然后我去取消订阅处理程序内部的事件,因为我是一个聪明和干净的人,不希望泄漏。我也不想在这里用一些精美的纺织厂或类似的东西来打破任何飞在轮子上的苍蝇。

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

    1. 这通常是一种足够干净的方法来取消订阅处理程序内部的事件处理程序吗?还是最终会杀死一只无辜的小狗?
    2. 在匿名委托中使用外部作用域变量可能会出现一些问题,比如泄漏吗?
    3. 是否有线程同步问题会导致我“错过” Loaded 事件?在这个特殊的场景中,只应涉及Silverlight的UI Dispatcher线程。但是,如果这仍然是一个问题,并且/或者如果我在一个非UI相关的场景中需要类似的功能,那么F1X0R IT的最佳方法是什么?

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

    1 回复  |  直到 14 年前
        1
  •  2
  •   Jon Skeet    14 年前
    1. 那应该很好,虽然有点痛。linq-to-rx有一个更好的取消订阅的想法-当你订阅时,你会得到一个 IDisposable 当你处理它时会取消订阅。但这不适合现有的事件模型。
    2. 我认为在这种特殊情况下不会有任何泄漏——在某些边缘条件下,使用相同范围内变量的两个不同匿名函数最终都可以捕获它们不需要的变量,但这确实是边缘情况。
    3. 你必须给出关于假设情况的更准确的细节——你到底担心什么,事件是如何实现的等等。