简体   繁体   English

如何确定是否正在卸载C#控件?

[英]How to determine whether a C# control is being unloaded?

In my C# Windows Forms application, I have a user control that contains other controls and does its own logic. 在我的C#Windows Forms应用程序中,我有一个用户控件,该控件包含其他控件并具有自己的逻辑。 One of them is a delayed call (Timer-invoked) that does certain things after the user has finished a keyboard input (live filter text). 其中之一是延迟调用(调用计时器),该延迟调用在用户完成键盘输入(实时过滤器文本)后执行某些操作。 It accesses the other controls for this, one of them is that text input control. 为此,它访问其他控件,其中之一是文本输入控件。 This method is invoked 500 ms after the last input event. 在上次输入事件后500毫秒调用此方法。

Now I have a problem when the delayed call is running while the application is terminating. 现在,当应用程序终止时延迟调用正在运行时,我遇到了一个问题。 When I enter some text, then wait about 500 ms (it seems to work every time) and then press Alt+F4 to close the window, the application throws a NullReferenceException while trying to access the text input control. 当我输入一些文本时,等待大约500毫秒(似乎每次都起作用),然后按Alt + F4关闭窗口,应用程序在尝试访问文本输入控件时会抛出NullReferenceException。 This doesn't happen when I close the window immediately after the last input or a second or more after. 当我在上次输入后立即关闭窗口或在此后一秒或更长时间关闭窗口时,不会发生这种情况。

It seems that the control is being disposed or something and its methods cannot access the child controls anymore. 似乎该控件正在被处置,或者某种方法及其方法无法再访问子控件。 So, when the control is being put in that state (by whomever and whatever that state exaclty is), those timer need to be stopped first so that the controls can be safely disposed. 因此,当控件处于该状态时(无论该状态是由谁执行的,无论该对象处于何种状态),都需要首先停止那些计时器,以便可以安全地放置控件。

I have already tried to stop the timer in the OnHandleDestroyed method (overridden) and at the beginning of the Designer-generated Dispose method. 我已经尝试过在OnHandleDestroyed方法(重写)和Designer生成的Dispose方法的开始处停止计时器。 Nothing helped. 没有任何帮助。

This procedure works fine in regular Forms when stopping the timers in the overridden OnFormClosed method, before calling base.OnFormClosed(). 在调用base.OnFormClosed()之前,在重写的OnFormClosed方法中停止计时器时,此过程在常规Forms中可以正常工作。 I just cannot find a suitable event in a user control. 我只是在用户控件中找不到合适的事件。

Try this in your UserControl: 在您的UserControl中尝试以下操作:

bool isDisposed;
protected override void Dispose(bool disposeManaged)
{
    if(!isDisposed)
    {
        if(disposeManaged)
        {
            //Dispose your timer here
        }
        isDisposed = true;
    }
}

Another possibility is that one of your UI classes doesn't do its cleanup. 另一种可能是您的一个UI类没有进行清理。 Eg. 例如。 it registers itself for an event but doesn't deregister when it's manually disposed. 它会为事件注册自己,但在手动处理事件时不会取消注册。 It is never collected by the GC and when the event is fired for the next time, it tries to access some members that were set to null during the Dispose(...) call before. GC永远不会收集它,并且下次触发该事件时,它将尝试访问之前在Dispose(...)调用期间设置为null的某些成员。

Another possibility is that you have a more complex race condition within your code but it's hard to say from here. 另一种可能性是您的代码中存在更复杂的竞争条件,但是从这里很难说。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM