.net 匿名委托的事件处理

.net 匿名委托的事件处理,.net,events,anonymous-delegates,.net,Events,Anonymous Delegates,记录在案:我发现了一个类似的问题,但我必须在这个问题上做更多的阐述 我的具体设想是: 在Silverlight4中,myFrameworkElement.FindName(“otherElementName”)方法现在似乎工作正常,但我遇到了一个问题。当元素尚未添加到可视化树中时,它仍然返回null 但是现在我需要在自定义用户控件的依赖属性的属性ChangedCallback处理程序中使用此功能。在此范围内,还不确定UserControl是否已添加到可视化树中。但我必须对树中的另一个元素执行某个

记录在案:我发现了一个类似的问题,但我必须在这个问题上做更多的阐述

我的具体设想是:

在Silverlight4中,
myFrameworkElement.FindName(“otherElementName”)
方法现在似乎工作正常,但我遇到了一个问题。当元素尚未添加到可视化树中时,它仍然返回
null

但是现在我需要在自定义
用户控件的
依赖属性
属性ChangedCallback
处理程序中使用此功能。在此范围内,还不确定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;
            }
        }
扩展方法的代码如下所示:

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;
            }
        }
static public void findnamesured(此框架元素本身,
字符串名称、操作结果(ON)
{
if(self!=null&&resultAction!=null)
{
对象结果=self.FindName(名称);
如果(结果!=null)
{
结果(result);
}
其他的
{
RoutedEventHandler处理程序=null;
处理程序=(发送方,e)=>
{
结果=self.FindName(名称);
结果(result);
self.load-=处理程序;
};
self.load+=处理程序;
}
}
正如您所看到的,我必须使用匿名委托,因为我需要处理程序内部的
name
resultAction
的值。然后我在处理程序内部取消订阅事件,因为我是一个聪明干净的人,不想泄露。我也不想在这里用一些花哨的薄弱工厂来打破任何障碍或者类似的东西

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

  • 这通常是一种足够干净的方法来取消处理程序内部的事件处理程序吗?还是最终会杀死一只无辜的小狗
  • 由于在匿名委托中使用外部作用域变量,是否会出现一些问题,如泄漏
  • 是否会出现线程同步问题,导致我“错过”加载的
    事件?在这种特殊情况下,应该只涉及Silverlight的UI dispatcher线程。但是,如果这是一个问题,并且/或者如果我在与UI无关的情况下需要类似的功能,那么最好的方法是什么
  • 已经感谢您的耐心和时间阅读我冗长的阐述。;-)

  • 这应该没问题,虽然有点痛苦。LINQ to Rx对取消订阅有一个更好的想法-当你订阅时,你会得到一个
    IDisposable
    ,当你处理它时,它会取消订阅。但这不适合现有的事件模型
  • 我不认为在这种特殊情况下会有任何泄漏-存在一些边缘条件,即两个不同的匿名函数在同一范围内使用变量,最终可能捕获到它们不需要的变量,但这确实是一种边缘情况
  • 你必须给出关于假设情况的更确切的细节——你到底担心什么,事件是如何实施的等等

  • 好的,谢谢你的回答,斯基特先生。关于第(3)点,一旦我发现一个场景,或者它已经成为一个严重的问题,我会回来或发布一个新的问题