NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: .FormClosed event v hlavním okně a v a okně close na exception... vyhodi exception: K uvolněnému objektu nelze přistupovat.

V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Dog
Člen
Avatar
Dog:5.11.2016 13:56

V hlavním okně:

private void btnGroupClick(object sender, EventArgs e)
{
    if (!isOpenedEditGroups)
    {
        A a = new A();
        a.Show();
        isOpenedEditGroups = true;

        //Tohle způsobuje vyjímku, ale nevím, jak ji podchtit
        a.FormClosed += GroupEditClosedEvent;
    }
}
private void GroupEditClosedEvent(object sender, FormClosedEventArgs e)
{
    isOpenedEditGroups = false;
}

V a konstruktor:

InitializeComponent();

try
{
    //inicializace s groupsettings (IO)...
}
catch
{
    MessageBox.Show("There is missing file settings.grh,\nGRH will not work correctly.", "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
    Close();
}

Díky :)

 
Odpovědět
5.11.2016 13:56
Avatar
D0ll0k
Člen
Avatar
D0ll0k:5.11.2016 15:15

K a.FormClosed musíš přiřadit event handler FormClosedEven­tHandler a ne jenom metodu:

a.FormClosed += new FormClosedEventHandler(nazev_metody);
Nahoru Odpovědět
5.11.2016 15:15
Veni, vidi, programmato
Avatar
Dog
Člen
Avatar
Dog:5.11.2016 17:07

To na to nemá vliv... Může tam být jen metoda...
Zjistil jsem, že na to nemá vůbec vliv ten event, ale samotné close v tom exceptionu v konstruktoru...

//konstruktor
public A()
{
    InitializeComponent();

    try
    {
        using (StreamReader reader = new StreamReader(@"settings.grh"))
        {

            string[] file = File.ReadAllLines(@"settings.grh");
            List<string> list = new List<string>();
            list.AddRange(file);
            foreach (string line in list)
            {
                if (line.Contains("[GROUP="))
                {
                    string[] temp = line.Split('=');
                    listGroups.Items.Add(temp[1].Replace("]", ""));
                }
            }
        }
    }
    catch
    {
        MessageBox.Show("There is missing file settings.grh,\nGRH will not work correctly.", "Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        Close();        //TOHLE ZPUSOBUJE CHYBU
    }


    foreach (Control objekt in Controls)
    {
        if (objekt is ComboBox)
            ((ComboBox)objekt).SelectedIndexChanged += new EventHandler(EventComboChanged);
    }

    textAddGroup.Text = "Group Name";
    textAddGroup.ForeColor = Color.Gray;
    textAddPlayer.Text = "Player Name";
    textAddPlayer.ForeColor = Color.Gray;
}

Chyba:

Neošetřená výjimka typu System.ObjectDisposedException vznikla v System.Windows.Forms.dll.

Další informace: K uvolněnému objektu nelze přistupovat.
Editováno 5.11.2016 17:08
 
Nahoru Odpovědět
5.11.2016 17:07
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:5.11.2016 22:14

Zavírat form hned v konstruktoru je poměrně "nestandartní" :-) postup. A ani to nepotřebuješ - když ti konstruktor form nevytvoří, tak ho ani nemusíš zavírat.
Navíc se pokoušíš přistupovat k objektu, který jsi vlastně ani nevytvořil.

Co se týče neošetřené vyjímky - ty ji musíš poslat dál a někde zpracovat.

Něco si o vyjímkách nastuduj - třeba tady

mělo by to vypadat zhruba takto:

public A()
        {
            InitializeComponent();

            try
            {
                using (StreamReader reader = new StreamReader(@"settings.grh"))
                {

                    string[] file = File.ReadAllLines(@"settings.grh");
                    List<string> list = new List<string>();
                    list.AddRange(file);
                    foreach (string line in list)
                    {
                        if (line.Contains("[GROUP="))
                        {
                            string[] temp = line.Split('=');
                            listGroups.Items.Add(temp[1].Replace("]", ""));
                        }
                    }
                }
            }
            catch
            {
                if (MessageBox.Show("There is missing file settings.grh,\nGRH will not work correctly.", "Error",
                                  MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.OK)
                    throw new Exception("nejaky problem :(");

            }


            foreach (Control objekt in Controls)
            {
                if (objekt is ComboBox)
                    ((ComboBox)objekt).SelectedIndexChanged += new EventHandler(EventComboChanged);
            }

            textAddGroup.Text = "Group Name";
            textAddGroup.ForeColor = Color.Gray;
            textAddPlayer.Text = "Player Name";
            textAddPlayer.ForeColor = Color.Gray;
        }
      private void btnGroupClick(object sender, EventArgs e)
        {
            if (!isOpenedEditGroups)
            {
                try
                {
                A a = new A();
                a.Show();
                isOpenedEditGroups = true;
                a.FormClosed += GroupEditClosedEvent;
                }

                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "pozor", MessageBoxButtons.OK);
                }
;
            }
        }
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
5.11.2016 22:14
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na D0ll0k
ostrozan:5.11.2016 22:24

K a.FormClosed musíš přiřadit event handler FormClosedEven­tHandler a ne jenom metodu:

to bylo dřív - ve VS2015 (možná i VS2013, nevím) už to být nemusí

 
Nahoru Odpovědět
5.11.2016 22:24
Avatar
Honza
Člen
Avatar
Honza:5.11.2016 23:14

Problém bude zřejmě v tom, že se pokoušíš form zavřít už v konstruktoru, kde ale ještě není úplně vytvořený. V konstruktoru bys měl maximálně nastavovat nějaké property které si vytvoříš, ale ne sahat na UI nebo form zavírat.

Místo kde to můžeš bezpečně udělat, protože už je všechno vytvořeno, je při vyvolání eventu Loaded (týká se jenom WPF) nebo Shown (týká se winformů). U winformů je ještě event Load, ale tam bych byl taky opatrný, nejsem si úplně jistý co všechno je při jeho zavolání už vytvořeno a co ještě ne.

Nahoru Odpovědět
5.11.2016 23:14
Snadnou cestou se daleko nedostanete, je tam velká tlačenice...
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Honza
ostrozan:5.11.2016 23:50

Myslím, že když dojde k vyjímce v konstruktoru,tak to Garbage Collector všechno uklidí.(ale jistě to nevím)

ale to že má v konstruktoru věci, které by tam být neměly je pravda

 
Nahoru Odpovědět
5.11.2016 23:50
Avatar
Dog
Člen
Avatar
Dog:6.11.2016 0:01

Já vím, samozřejmě bych to mohl vyřešit takhle:

try
{
    Options options = new Options();
    options.Show();
    isOpenedEditGroups = true;
    options.FormClosed += new FormClosedEventHandler(GroupEditClosedEvent);
}
catch
{
    MessageBox.Show("////", "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}

Ale zajímalo mě, jak to vyřešit takhle :-) Díky

Editováno 6.11.2016 0:01
 
Nahoru Odpovědět
6.11.2016 0:01
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Dog
ostrozan:6.11.2016 0:15

Honza má pravdu - dej to radši do obsluhy události Load, nebo Shown

private void A_Load(object sender, EventArgs e)
{
    try
    {
        using (StreamReader reader = new StreamReader(@"settings.grh"))
        {

            string[] file = File.ReadAllLines(@"settings.grh");
            List<string> list = new List<string>();
            list.AddRange(file);
            foreach (string line in list)
            {
                if (line.Contains("[GROUP="))
                {
                    string[] temp = line.Split('=');
                    listGroups.Items.Add(temp[1].Replace("]", ""));
                }
            }
        }
    }
    catch (Exception ex)
    {

       if (MessageBox.Show(ex.Message, "Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.OK)
        {
          Close();
        }

       throw new Exception(ex.Message);
    }
}

tohle ti přímo hodí hlášku do MessageBoxu, že "soubor settings.grh nebyl nalezen"

Editováno 6.11.2016 0:18
 
Nahoru Odpovědět
6.11.2016 0:15
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.