C# - 确保事件不要堆叠

时间:2011-03-18 13:46:49

标签: c# events

HI,

我有一个按钮点击事件,其中初始化了用户定义的类型,并设置了一个事件。

此按钮被多次使用,我不希望事件堆叠。因此,我已经取消订阅了finally块中的事件。

代码类似于以下内容:

try {
bar = new foo();
bar.event += new event(method);

dosomething()
}
finally {
bar.event -= new event(method);
}

到目前为止似乎工作正常,但是我关注在doSomething方法完成之前处理的finally块,从而使用了事件。

在调用finally块之前,是否允许该方法进行处理?

8 个答案:

答案 0 :(得分:6)

我通常做的是每次触发事件时都会检查一个inEvent布尔变量。代码如下所示:

bool inEvent = false;

...

private void Button1_Click(object source, EventArgs e) 
{
    if (inEvent)
        return;

    try 
    {
        inEvent= true;

        dosomething();
    }
    finally 
    {
        inEvent = false;
    }
}

答案 1 :(得分:3)

时,finally块将执行
  1. dosomething已成功完成
  2. dosomething抛出异常
  3. foo构造函数抛出异常
  4. 在最后一种情况下,它将访问未初始化的变量栏并抛出NullReferenceException。所以你最好把bar = new foo();放在try块之前。

答案 2 :(得分:2)

根据定义,finally块只能在执行离开dosomething()方法的主体之后才会出现,如果通过函数的return语句或normale结尾或者在此方法的主体内抛出的异常在这个函数中没有处理。

答案 3 :(得分:1)

finally块在dosomething返回或抛出之前不会运行。

答案 4 :(得分:1)

最好在生成的事件中取消订阅。

void somewhere()
{
    bar = new foo();
    bar.event += method;
    dosomething()
}

void method(object source, EventArgs e)
{
    ((bar)source).event -= method;
}

答案 5 :(得分:0)

是(除非在此之前抛出异常)。你的想法很合理。

答案 6 :(得分:0)

据推测,DoSomething()中的逻辑引发了您感兴趣的事件?如果是这样,如果DoSomething()异步引发事件,则会出现问题 - 如果是这种情况,DoSomething可能会返回,那么您最终将运行并取消订阅该事件。当事件最终从DoSomething中启动的代码触发时,你会错过它。

如果DoSomething中没有异步逻辑(即如果事件是同步引发的),那么您的一般方法就可以了。但是你可能想要考虑让DoSomething返回一个值,而不是提出一个事件

答案 7 :(得分:0)

同步调用事件。因此,除非您在DoSomething()方法中编写任何异步代码,否则最终将在执行完成后始终运行(或抛出异常)。

您似乎得到的是,挂起的事件处理程序引用将阻止收集对象,这可能导致内存问题。您有正确的想法,为了完全释放和反对,您应该在完成后删除所有事件。