2017-06-08 1 views
-1

Ich habe ein kleines Problem mit meinen Objekten ... Ich habe ein Objekt mit einem Delegaten innerhalb, die es im Konstruktor abonnieren. Wenn ich dieses Objekt zerstöre, sagt die Aufrufliste immer noch, dass es einen Abonnenten hat. Und wenn ich dieses Objekt erneut anlege, finde ich zwei Abonnenten (das alte, das ich zerstört habe und das neue). Wie kann ich dieses Problem lösen und den Abonnenten in der Liste sauber entfernen? HierZerstörendes Objekt entfernt Delegat nicht aus Aufrufliste

ist der Code für den Test: (mit zwei Tasten zu zerstören und erstellen Objekt in)

public partial class Form1 : Form 
{ 
    testdelegate thisdelegatetest; 
    public Form1() 
    { 
     InitializeComponent(); 
     thisdelegatetest = new testdelegate();//create object 
     Timer mytimer = new Timer();//timer to see something BEGIN 
     mytimer.Interval = 1000; 
     mytimer.Tick += new EventHandler(mytimer_Tick); 
     mytimer.Start();//timer to see something END 
    } 
    protected void mytimer_Tick(object sender, EventArgs e) 
    {//each 1second look at the list invocation 
     lb_IndelList.Text = "actual subscribers : " + testdelegate.dl_myfunctionthatcopy.GetInvocationList().Count().ToString(); 
    } 
    private void DestroyObject_Click(object sender, EventArgs e) 
    {//destroy object 
    /*edit*/ 
     thisdelegatetest.Delete(); 
     thisdelegatetest = null;//dereferencing for GC 
    /*edit*/ 
    } 

    private void CreateObject_Click(object sender, EventArgs e) 
    {//create object 
     thisdelegatetest = new testdelegate(); 
    } 

} 
public class testdelegate 
{ 
    public delegate void del_copysomething(int newvaluetocopy); 
    internal static del_copysomething dl_myfunctionthatcopy; 
    public int valueforallobject = 0; 

    public testdelegate()//ctor 
    { 
     dl_myfunctionthatcopy += new del_copysomething(copythisint); 
    } 
    /*edit*/ 
    public void Delete() 
    { 
     dl_myfunctionthatcopy -= new del_copysomething(copythisint); 
    } 
    /*edit*/ 
    private void copythisint(int newvalue) 
    { 
     valueforallobject = newvalue; 
    } 
} 

Vielen Dank für Ihre Hilfe.

+1

eine variable Einstellung auf 'null' ist * nicht * "zerstören" ein Objekt aus. Was auch immer Ihr mentales Modell für die Funktionsweise von Objekten in C# ist, es ist falsch. –

+0

Können Sie bitte die vorgenommenen Änderungen erklären? – Enigmativity

+1

Bitte editiere deine Frage nicht so, dass * das Problem nicht mehr auftritt und das keinen Sinn ergibt *. –

Antwort

0

Da Sie den Destruktor nicht manuell aufrufen können, warum implementieren Sie nicht die IDisposable Schnittstelle und führen die Aufhebung der Registrierung in der Dispose Methode aus? =!

public class testdelegate : IDisposable 
{ 
    public delegate void del_copysomething(int newvaluetocopy); 
    internal static del_copysomething dl_myfunctionthatcopy; 
    public int valueforallobject = 0; 

    public testdelegate()//ctor 
    { 
     dl_myfunctionthatcopy += new del_copysomething(copythisint); 
    } 
    private void copythisint(int newvalue) 
    { 
     valueforallobject = newvalue; 
     Console.WriteLine("Copied"); 
    } 

    public void Dispose() 
    { 
     dl_myfunctionthatcopy -= new del_copysomething(copythisint); 
     GC.SuppressFinalize(this); 
    } 
} 

Im DestroyObject_Click Methode würden Sie rufen Sie einfach die Dispose Methode:

private void DestroyObject_Click(object sender, EventArgs e) 
{ //call Dispose destroy object 
    thisdelegatetest.Dispose(); 
} 
+0

Vielen Dank an alle !! – Jablonovo

+0

@Jablonovo Ich denke, es hat funktioniert, ich habe es nicht getestet. Froh, dass ich helfen konnte –

1
private void DestroyObject_Click(object sender, EventArgs e) 
{//destroy object 
    thisdelegatetest = null; 
} 

Dies zerstört das Objekt nicht wirklich. Objekte werden vom Garbage Collector "zerstört" (befreit).

In der Tat kann es nicht als sammelbar markiert werden, da der static Delegat immer noch darauf verweist. Daher wird der Destruktor niemals aufgerufen. Sie haben den Teilnehmer manuell entfernt, z. durch eine öffentliche Methode.

+4

Außer in diesem Fall ist das Objekt nicht für GC geeignet, gerade weil ein Delegat immer noch darauf verweist –

+0

"Es dauert zwei Garbage Collection-Zyklen, bis der Destruktor aufgerufen wird." - Können Sie einen Hinweis zur Unterstützung dieser Aussage geben? – Enigmativity

+0

Die Aussage "Dies zerstört das Objekt nicht wirklich" ist ein bisschen irreführend. Es deutet darauf hin, dass es das Objekt irgendwie zerstört oder etwas zerstört. Es zerstört es überhaupt nicht. – Enigmativity