尝试布置控件时出现的竞争状况 [英] race condition when trying to dispose a control

查看:69
本文介绍了尝试布置控件时出现的竞争状况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我似乎在某种比赛条件下奔跑.这是问题的非常简化的版本. (实际上,它们之间有几层,这些控件不是Button,而是从Control等继承的.)我需要在例如之后删除并处理我的控件.请假事件如下.
如果单击button1,则会得到一个ObjectDisposedException,因为它需要完成一些操作.如果我单击button2,它将非常有效.
准备好要处置时,我怎么才能知道呢?或者如何强制控件在处理之前完成它需要做的所有工作?
一个可能的解决方案应该适用于Control的所有继承.
(我的第一个天真尝试是只是停止所有消息,如下面的代码所示.对于Application.DoEvents()也不起作用)

谢谢!

Hi

I seem to have run in kind of a race condition. This is the very simplified version of the problem. (In reality there are several layers inbetween, the controls are no Buttons, but also inherited from Control etc.) I _need_ to remove and dispose my controls after e.g. a leave event as below.
If I click on button1 I get an ObjectDisposedException, because it needs to finish something. If I click on button2 it obviuously works.
How can I find out, when it is ready to be disposed? Or how can I force a Control to finish all it needs to do before disposing?
A possible solution should work for all inheritances of Control.
(My first maybe naive try was just to stop all messages as in code below. Nor helps an Application.DoEvents())

THANK YOU!

using System;
using System.Windows.Forms;

namespace Test
{
    static class Program
    {
        static void Main()
        {
            Application.Run(new TestForm());
        }

        public class TestForm : Form
        {

            myButton button1;
            myButton button2;

            public TestForm()
            {
                TextBox tb = new TextBox();
                Controls.Add(tb);


                button1 = new myButton();
                button1.Text = "button1";
                button1.Location = new System.Drawing.Point(tb.Right, 0);
                Controls.Add(button1);

                button2 = new myButton();
                button2.Text = "button2";
                button2.Location = new System.Drawing.Point(button1.Right, 0);
                Controls.Add(button2);

                tb.Leave += new EventHandler(tb_Leave);
            }

            void tb_Leave(object sender, EventArgs e)
            {
                Controls.Remove(button1);
                button1.WillBeDisposed = true;

                //this will throw an ObjectDisposedException if the Leave event was caused by clicking on button1
                //this will NOT throw an ObjectDisposedException if the Leave event was caused by clicking on button2

                //How can I find out at which point of time the button (or any other Control) can be safely disposed, or how can I force button1 to finish all it needs to do?

                button1.Dispose();
            }
        }

        public class myButton : Button
        {
            internal bool WillBeDisposed = false;
            protected override void WndProc(ref Message m)
            {
                if (WillBeDisposed) return; //doesn''t help
                base.WndProc(ref m);
            }
        }
    }
}

推荐答案

如果您确实需要:

1.在类myButton中明确实现IDisposable.
2.如果父类实现Dispose(),请确保在函数的第一行中调用父版本.
3.别忘了打电话给GC.SuppressDispose()(或类似的名字,我不记得确切的名字了); google上的"IDisposable实现".

但是,您不必一定要这么做.
仅当它们包含资源(数据库连接,套接字,文件句柄,GDI句柄...)时,才需要使它们成为一次性对象.
表单和控件不应该管理资源:这就是MVC模式(以及所有从其派生的模式)的目的.只有模型中的类才可以管理资源.

希望这会有所帮助,

巴勃罗.
If you really have to:

1. Explicitly implement IDisposable in class myButton.
2. If the parent class implements Dispose(), make sure you call the parent version in the first line of your function.
3. Don''t forget to call GC.SuppressDispose() (or similar, I don''t remember the exact name); google for ''IDisposable implementation''.

But you don''t really have to.
You only have to make disposable objects if they contain resources (database connections, sockets, file handles, GDI handles, ...).
Forms and controls are not supposed to manage resources: that''s what the MVC pattern (and all those derived from it) is all about. Only classes in the Model should manage resources.

Hope this helps,

Pablo.


这篇关于尝试布置控件时出现的竞争状况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆