Forum: PC-Programmierung NullReferenceException bei Aufruf einer Methode


von Schlumpf (Gast)


Lesenswert?

Hallo, beim Ausführen des unten gezeigten Programmteiles gibt es eine 
Fehlermeldung (als Kommentar angefügt).
Der Fehler ist zwar behoben, wenn ich, wie es VisualStudio vorschlägt, 
eine neue Instanz anlege, aber ich will mich ja auf genau das Objekt 
beziehen, was ich in "twincat_ads_vorbereitung()" erstellt habe.
Was muss ich tun, damit der Aufruf auch in einer anderen Methode 
funktioniert?
1
public partial class Form1
2
    {
3
        public TcAdsClient adsClient;
4
        private int handle_start;
5
        bool aktivieren = false;
6
        
7
        public static void form_geladen()
8
        {
9
            Form1 instanz = new Form1();    
10
            instanz.twincat_ads_vorbereitung();   
11
        }
12
13
        public void twincat_ads_vorbereitung()
14
        {
15
            adsClient = new TcAdsClient();
16
17
            try
18
            {
19
                adsClient.Connect(851);
20
                handle_start = adsClient.CreateVariableHandle("MAIN.aktivieren");
21
            }
22
            catch (Exception ausnahme)
23
            {
24
                MessageBox.Show("Fehlerquelle: " + ausnahme.Source+
25
                                "\nBeschreibung: "+ausnahme.Message,
26
                                "Fehler ADS-Vorbereitung", MessageBoxButtons.OK,
27
                                MessageBoxIcon.Error);
28
            }
29
        }
30
31
        public void twincat_ads_dispose()
32
        {
33
            MessageBox.Show("TwinCAT ADS", "Beenden", MessageBoxButtons.OK, MessageBoxIcon.Hand);
34
            adsClient.Dispose(); //System.NullReferenceException wurde nicht behandelt.Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
35
36
        }
37
    }
38
}

von Sam P. (Gast)


Lesenswert?

Hast du geprüft, ob ..._vorbereitung auch wirklich vor ..._dispose 
aufgerufen wurde und Erfolg hatte? Wird ..._dispose vielleicht zweimal 
aufgerufen?

Einfache printf-Statements (ich kenne C# nicht, ersetze durch was 
gleichwertiges) am Anfang der Funktionen könnten dir weiterhelfen.

von Schlumpf (Gast)


Lesenswert?

ja, die Reihenfolge ist geprüft und war auch richtig. Ich habe das 
Programm noch etwas umgestellt und mal einen Schreibzugriff ausprobiert. 
Das funktioniert auch wunderbar - solange ich in einer Methode bleibe -. 
Ich würde aber gerne aus mehreren Methoden auf das Handle zugreifen.
1
    class Funktionen
2
    {
3
        private TcAdsClient adsClient = new TcAdsClient();
4
        
5
        private int handle_start;
6
        bool aktivieren = false;
7
8
        public static void form_geladen()
9
        {         
10
            Funktionen instanz = new Funktionen();   
11
            instanz.twincat_ads_vorbereitung();
12
        }
13
14
        public void twincat_ads_vorbereitung()
15
        {
16
            try
17
            {
18
                adsClient.Connect(851);
19
                handle_start = adsClient.CreateVariableHandle("MAIN.aktivieren");
20
                adsClient.WriteAny(handle_start, true); //Hier funktioniert es, SPS läuft los
21
                Console.WriteLine("Geöffnet\n");
22
            }
23
            catch (Exception ausnahme)
24
            {
25
                MessageBox.Show("Fehlerquelle: " + ausnahme.Source+
26
                                "\nBeschreibung: "+ausnahme.Message,
27
                                "Fehler ADS-Vorbereitung", MessageBoxButtons.OK,
28
                                MessageBoxIcon.Error);
29
            }
30
        }
31
32
        
33
        public static void ads_schreiben()
34
        {
35
            Funktionen inst = new Funktionen();
36
            inst.adsClient.WriteAny(inst.handle_start, inst.aktivieren);
37
            //HIER FEHLER
38
        }
39
    }
40
}

von Warhawk (Gast)


Lesenswert?

Da nicht der ganze Quelltext vorliegt, kann ich nur ratten.
Du legst eine neue Instanz von Funktionen an, rufst aber deine 
Vorbereitenmethode nie für dieses Objekt auf.

Versuch mal folgendes:
1
Funktionen inst = new Funktionen();
2
inst.twincat_ads_vorbereitung();
3
inst.adsClient.WriteAny(inst.handle_start, inst.aktivieren);

Grüße, Warhawk

von Schlumpf (Gast)


Lesenswert?

Danke, damit scheint es zu funktionieren!

Wird dabei dann jedes mal ein neues Handle erzeugt? Ich will ja 
eigentlich nur einen adsClient haben, mit dem ich mich auch nur einmal 
verbinde. Die anderen MEthoden sollen nur darauf zugreifen.

von Warhawk (Gast)


Lesenswert?

Ok dann mach mal folgendes:
1
    class Funktionen
2
    {
3
        private static Funktionen m_Inst = null;
4
5
        private TcAdsClient adsClient = new TcAdsClient();
6
        
7
        bool aktivieren = false;
8
9
        public static void form_geladen()
10
        {         
11
            m_Inst = new Funktionen();   
12
            m_Inst.twincat_ads_vorbereitung();
13
        }
14
15
        public void twincat_ads_vorbereitung()
16
        {
17
            try
18
            {
19
                adsClient.Connect(851);
20
                handle_start = adsClient.CreateVariableHandle("MAIN.aktivieren");
21
                adsClient.WriteAny(handle_start, true); //Hier funktioniert es, SPS läuft los
22
                Console.WriteLine("Geöffnet\n");
23
            }
24
            catch (Exception ausnahme)
25
            {
26
                MessageBox.Show("Fehlerquelle: " + ausnahme.Source+
27
                                "\nBeschreibung: "+ausnahme.Message,
28
                                "Fehler ADS-Vorbereitung", MessageBoxButtons.OK,
29
                                MessageBoxIcon.Error);
30
            }
31
        }
32
33
        
34
        public static void ads_schreiben()
35
        {
36
            m_Inst.adsClient.WriteAny(inst.handle_start, inst.aktivieren);
37
            //HIER FEHLER
38
        }
39
    }

Das ist aber aus Objekt orientierter Sicht nicht ganz sauber.
Ich würde ohne die static-Methoden arbeiten und die Referenz auf die 
Instanz von Funktionen an alle Klassen übergeben die damit arbeiten 
sollen.

Du legst in deiner Klasse für die Anwendungslogik eine Instanz von 
Funktionen an, speicherst sie in einer Membervariable und reicht sie von 
dort aus an alle Klassen weiter die damit arbeiten sollen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.