473,772 Members | 3,712 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Events, weak references or other approach advice required

Hi, I've just written the following code to describe the issue I have.
In a nutshell if an object subscribes to an event on a long lived
object and I then ditch the reference to the subscriber (set it to
null) The object doesn't get GCed because the publisher still has a
reference to it.
Solutions I can think of are:
1) WeakReference - I'm not sure how to do that (Needs to be framework
1.1 and 2 compatible fyi) and I'd like to use events rather than
delegates directly if that makes sense.
2) Implement an interface to explicitly unsubscribe the subscribers
(Doesn't have to be an interface, just a method for simplicity) but
then I have to remember to call that. Not a huge hassle, and something
I already do in other applications.

Here's the code.

//Publisher first
-------------------------------------------------------
using System;
using System.Timers;

namespace Eventer
{
public delegate void TimerEventHandl er(object sender, TimerEventArgs
e);
/// <summary>
/// Summary description for Publisher.
/// </summary>
public class Publisher
{
private Timer _timer=new Timer(2000);

public event TimerEventHandl er TimerFired;

public Publisher()
{
_timer.Elapsed+ =new ElapsedEventHan dler(_timer_Ela psed);
_timer.Start();
}
private void _timer_Elapsed( object sender, ElapsedEventArg s e)
{
TimerEventArgs nE=new TimerEventArgs( e.SignalTime.Ti cks);
OnTimerFired(nE );
}
protected virtual void OnTimerFired(Ti merEventArgs e)
{
if (null != TimerFired)
{
TimerFired(this ,e);
}
}
}

public class TimerEventArgs : EventArgs
{
long _tick=0;

public TimerEventArgs( long pTick)
{
_tick = pTick;
}

public long Tick
{
get
{
return _tick;
}
}
}
}

// Subscriber
---------------------------------------------------------------------

using System;

namespace Eventer
{
/// <summary>
/// Summary description for Subscriber.
/// </summary>
public class Subscriber
{
int _value;

public Subscriber(int pValue, Publisher pPublisher)
{
_value = pValue;
pPublisher.Time rFired+=new TimerEventHandl er(pPublisher_T imerFired);
}

private void pPublisher_Time rFired(object sender, TimerEventArgs e)
{
Console.WriteLi ne(_value.ToStr ing() + " - " + e.Tick.ToString ());
}
}
}

// The relevant bit of the form that tests it. Basically two buttons
one that starts and one that stops ------------------

private Publisher _publisber=new Publisher();
private System.Collecti ons.ArrayList _arrayList=new ArrayList(5);

//Create subscribers
private void button1_Click(o bject sender, System.EventArg s e)
{
Subscriber s;

for(int c=0;c<5;c++)
{
s=new Subscriber(c,_p ublisber);
_arrayList.Add( s);
}

}

//clear reference to subscribers
private void button2_Click(o bject sender, System.EventArg s e)
{
_arrayList=null ;
GC.Collect(); //trying to hurry things along for the demo
}

Sep 11 '06 #1
4 1569
One suggestion is to make the objects Disposable and then dispose them before
setting them to null. Then in the Dispose function you can un register them
from the event.
Ciaran O'Donnell

"DeveloperX " wrote:
Hi, I've just written the following code to describe the issue I have.
In a nutshell if an object subscribes to an event on a long lived
object and I then ditch the reference to the subscriber (set it to
null) The object doesn't get GCed because the publisher still has a
reference to it.
Solutions I can think of are:
1) WeakReference - I'm not sure how to do that (Needs to be framework
1.1 and 2 compatible fyi) and I'd like to use events rather than
delegates directly if that makes sense.
2) Implement an interface to explicitly unsubscribe the subscribers
(Doesn't have to be an interface, just a method for simplicity) but
then I have to remember to call that. Not a huge hassle, and something
I already do in other applications.

Here's the code.

//Publisher first
-------------------------------------------------------
using System;
using System.Timers;

namespace Eventer
{
public delegate void TimerEventHandl er(object sender, TimerEventArgs
e);
/// <summary>
/// Summary description for Publisher.
/// </summary>
public class Publisher
{
private Timer _timer=new Timer(2000);

public event TimerEventHandl er TimerFired;

public Publisher()
{
_timer.Elapsed+ =new ElapsedEventHan dler(_timer_Ela psed);
_timer.Start();
}
private void _timer_Elapsed( object sender, ElapsedEventArg s e)
{
TimerEventArgs nE=new TimerEventArgs( e.SignalTime.Ti cks);
OnTimerFired(nE );
}
protected virtual void OnTimerFired(Ti merEventArgs e)
{
if (null != TimerFired)
{
TimerFired(this ,e);
}
}
}

public class TimerEventArgs : EventArgs
{
long _tick=0;

public TimerEventArgs( long pTick)
{
_tick = pTick;
}

public long Tick
{
get
{
return _tick;
}
}
}
}

// Subscriber
---------------------------------------------------------------------

using System;

namespace Eventer
{
/// <summary>
/// Summary description for Subscriber.
/// </summary>
public class Subscriber
{
int _value;

public Subscriber(int pValue, Publisher pPublisher)
{
_value = pValue;
pPublisher.Time rFired+=new TimerEventHandl er(pPublisher_T imerFired);
}

private void pPublisher_Time rFired(object sender, TimerEventArgs e)
{
Console.WriteLi ne(_value.ToStr ing() + " - " + e.Tick.ToString ());
}
}
}

// The relevant bit of the form that tests it. Basically two buttons
one that starts and one that stops ------------------

private Publisher _publisber=new Publisher();
private System.Collecti ons.ArrayList _arrayList=new ArrayList(5);

//Create subscribers
private void button1_Click(o bject sender, System.EventArg s e)
{
Subscriber s;

for(int c=0;c<5;c++)
{
s=new Subscriber(c,_p ublisber);
_arrayList.Add( s);
}

}

//clear reference to subscribers
private void button2_Click(o bject sender, System.EventArg s e)
{
_arrayList=null ;
GC.Collect(); //trying to hurry things along for the demo
}

Sep 11 '06 #2
try this:

System.IO.Strea mWriter file = new System.IO.Strea mWriter(@"C:\te st.xml");
System.Xml.XmlT extWriter xtr = new System.Xml.XmlT extWriter(file) ;
xtr.Formatting = System.Xml.Form atting.Indented ;
ser.Serialize(x tr, test);
file.Flush();
file.Close();
Ciaran O'Donnell
"DeveloperX " wrote:
Hi, I've just written the following code to describe the issue I have.
In a nutshell if an object subscribes to an event on a long lived
object and I then ditch the reference to the subscriber (set it to
null) The object doesn't get GCed because the publisher still has a
reference to it.
Solutions I can think of are:
1) WeakReference - I'm not sure how to do that (Needs to be framework
1.1 and 2 compatible fyi) and I'd like to use events rather than
delegates directly if that makes sense.
2) Implement an interface to explicitly unsubscribe the subscribers
(Doesn't have to be an interface, just a method for simplicity) but
then I have to remember to call that. Not a huge hassle, and something
I already do in other applications.

Here's the code.

//Publisher first
-------------------------------------------------------
using System;
using System.Timers;

namespace Eventer
{
public delegate void TimerEventHandl er(object sender, TimerEventArgs
e);
/// <summary>
/// Summary description for Publisher.
/// </summary>
public class Publisher
{
private Timer _timer=new Timer(2000);

public event TimerEventHandl er TimerFired;

public Publisher()
{
_timer.Elapsed+ =new ElapsedEventHan dler(_timer_Ela psed);
_timer.Start();
}
private void _timer_Elapsed( object sender, ElapsedEventArg s e)
{
TimerEventArgs nE=new TimerEventArgs( e.SignalTime.Ti cks);
OnTimerFired(nE );
}
protected virtual void OnTimerFired(Ti merEventArgs e)
{
if (null != TimerFired)
{
TimerFired(this ,e);
}
}
}

public class TimerEventArgs : EventArgs
{
long _tick=0;

public TimerEventArgs( long pTick)
{
_tick = pTick;
}

public long Tick
{
get
{
return _tick;
}
}
}
}

// Subscriber
---------------------------------------------------------------------

using System;

namespace Eventer
{
/// <summary>
/// Summary description for Subscriber.
/// </summary>
public class Subscriber
{
int _value;

public Subscriber(int pValue, Publisher pPublisher)
{
_value = pValue;
pPublisher.Time rFired+=new TimerEventHandl er(pPublisher_T imerFired);
}

private void pPublisher_Time rFired(object sender, TimerEventArgs e)
{
Console.WriteLi ne(_value.ToStr ing() + " - " + e.Tick.ToString ());
}
}
}

// The relevant bit of the form that tests it. Basically two buttons
one that starts and one that stops ------------------

private Publisher _publisber=new Publisher();
private System.Collecti ons.ArrayList _arrayList=new ArrayList(5);

//Create subscribers
private void button1_Click(o bject sender, System.EventArg s e)
{
Subscriber s;

for(int c=0;c<5;c++)
{
s=new Subscriber(c,_p ublisber);
_arrayList.Add( s);
}

}

//clear reference to subscribers
private void button2_Click(o bject sender, System.EventArg s e)
{
_arrayList=null ;
GC.Collect(); //trying to hurry things along for the demo
}

Sep 11 '06 #3
Hi,
"DeveloperX " <nn*****@operam ail.comwrote in message
news:11******** **************@ i42g2000cwa.goo glegroups.com.. .
Hi, I've just written the following code to describe the issue I have.
In a nutshell if an object subscribes to an event on a long lived
object and I then ditch the reference to the subscriber (set it to
null) The object doesn't get GCed because the publisher still has a
reference to it.
Solutions I can think of are:
1) WeakReference - I'm not sure how to do that (Needs to be framework
1.1 and 2 compatible fyi) and I'd like to use events rather than
delegates directly if that makes sense.
Not sure how (if) this will work.
2) Implement an interface to explicitly unsubscribe the subscribers
(Doesn't have to be an interface, just a method for simplicity) but
then I have to remember to call that. Not a huge hassle, and something
I already do in other applications.
I think this is the way to go with a twist, instead of a new interface you
could implement IDisposable and do your "cleaning" in the Dispose method.

You object will need a list of the subscriptions he did during its lifetime
and just unsubscribe from them. Not a terrible difficilt thing to implement
I think.

--
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

Sep 11 '06 #4

Ignacio Machin ( .NET/ C# MVP ) wrote:
Hi,
"DeveloperX " <nn*****@operam ail.comwrote in message
news:11******** **************@ i42g2000cwa.goo glegroups.com.. .
Hi, I've just written the following code to describe the issue I have.
In a nutshell if an object subscribes to an event on a long lived
object and I then ditch the reference to the subscriber (set it to
null) The object doesn't get GCed because the publisher still has a
reference to it.
Solutions I can think of are:
1) WeakReference - I'm not sure how to do that (Needs to be framework
1.1 and 2 compatible fyi) and I'd like to use events rather than
delegates directly if that makes sense.

Not sure how (if) this will work.
2) Implement an interface to explicitly unsubscribe the subscribers
(Doesn't have to be an interface, just a method for simplicity) but
then I have to remember to call that. Not a huge hassle, and something
I already do in other applications.

I think this is the way to go with a twist, instead of a new interface you
could implement IDisposable and do your "cleaning" in the Dispose method.

You object will need a list of the subscriptions he did during its lifetime
and just unsubscribe from them. Not a terrible difficilt thing to implement
I think.

--
--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
Yep, I use an interface as I wrap up registering and unregistering in
the same place. The event thing just suprised me for some reason, I'm
suprised I've not noticed it in the past, but I guess it doesn't
necessarily come up that often.
I'm as likely to register the subscribers with the publisher and have
the publisher call methods on the subscribers. Same issue of course,
Publisher holds a reference to the subscriber, but there you go.

Sep 11 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
2807
by: scsharma | last post by:
Hi, I am working on creating a webapplication and my design calls for creating main webform which will have menu bar on left hand side and a IFrame which will contain all the forms that are shown when menu items are clicked.Besides these i would like to put a custom status bar. Any error message encountered in any of the webpage will be displayed in the banner. The problem iam encountering is how to access the customer status bar in child...
4
1163
by: Dean Slindee | last post by:
Is there a shorter way of referring to another forms controls/events than creating a class hold forms, adding a form item each time a new form is loaded, and then looping thru the class of forms to find the reference? Like "friend", rather than like below: Public Class frmMain Private Sub frmMain_Load clsForm.Add(Me)
9
2192
by: Olivier Fermy | last post by:
I have created a sample project where i have referenced an object only with an event : textBox.VisibleChanged += new EventHandler(this.textBox_VisibleChanged); When i call GC.Collect(), the object is disposed and garbage collected ! I thought that event references are strong references and not weak references. Does the .NET 2.0 garbage collector manage differently the events references ?
16
2901
by: anonymous.user0 | last post by:
The way I understand it, if I have an object Listener that has registered as a listener for some event Event that's produced by an object Emitter, as long as Emitter is still allocated Listener will stay alive. Is this correct? If this is correct, I've got a problem. Let's say I've got an object Customer that has an PurchaseList (Collection) of Purchase objects. Now, these Purchase objects were pulled from a datasource Datasource. The...
30
3658
by: Burkhard | last post by:
Hi, I am new to C# (with long year experience in C++) and I am a bit confused by the language construct of events. What is it I can do with events that I cannot do with delegates? At the moment it seems to me that Microsoft has developed similar functionality via two keywords. I do understand that an event offers better encapsulation as the underlying delegate is private, but is that all ? -- Regards
5
2779
by: Daniel | last post by:
Hey guys When you hook an event (c# 2.0 syntax): myEvent += MyMethodToFire; You need to also unsubscribe it to avoid a resource leak so that the object it is in gets garbage collected like so : myEvent -= MyMethodToFire; That's all fine, but when you use visual studio to create events for objects it never creates an unsubscribing reference, so is it puting in resource leaks? Or is this being cleared somewhere that i am not seeing?
5
2081
by: Aleksey | last post by:
Hi all! It's a theoretical question. Suppose I have object A with event OnAction and I have object B that connects to this event. I create object B as a local method variable and in this method I connect object B to OnAction of object A. So after the method has finished running, the only way to reach object B is event in class A. How GC works in this case? Is it remove object B? If not than it may be a memory leak here!!!
11
3267
by: MikeT | last post by:
This may sound very elementary, but can you trap when your object is set to null within the object? I have created a class that registers an event from an object passed in the constructor. When my object is destroyed, I want my object to un-register this event. If I don't then the object would never be destroyed until the object I passed in the constructor is destroyed. I have implemented a Dispose(), Dispose(bool), and ~Finalize...
1
1769
by: Henri.Chinasque | last post by:
Hi all, I've been considering that my objects should subscribe to an event via a weak reference, however I've found several warnings that this approach comes with concurrency considerations, like the fact that the event handler method on the subscriber could be called and be executing while the object is being garbage collected. Not being super strong in the multithreaded department, I am having a hard time coming up with other...
0
9454
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10261
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10104
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9912
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8934
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6715
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5354
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5482
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4007
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.