Event subscribers disappear after inactivity

I have a class in a shared assembly which publishes several events. This shared assembly is shared between two applications and is used to pass client/server messages via remoting. My code works as expected, and the two application can share objects using the class' public delegates and raises notifications of messages received using the published events.

After several minutes of inactivity (that is, no events have been raised), the events will "loose" their subscribers. The event variables are non-null after the client app subscribes to them, but after a period of inactivity, the event variables will become null. Events that are periodically raised do not loose their subscribes, but those that are "still" for a minute or so will.

No destructors are being called, so I don;t think this is a garbage collection issue. When the client/server applications are not communicating, the only activity I see are the common "The thread 0xXXXX has exited with code 0 (0x0)." messages in the VS.NET Output window.

Does anyone know of why event subscribers would disappear after a period of inactivity

Thanks much.




Answer this question

Event subscribers disappear after inactivity

  • VladR

    It doesn't match your description, but, the only time I've seen this happen is when I create a delegate and pass it as a callback to a P/Invoke'd DLL method. The garbage collector is not aware of this unmanaged reference so cleans up the delegate instance when it gets a chance. Again, doubtful that this helps you along...


  • MichaelDugas

    Yes, using Invoke() to execute the delgate on a form's thread is exactly what I'm doing. I've tried using GC.KeepAlive() on the delegate to keep it from getting GC'ed, but this didn't fix the problem. I haven't found a way to determine if/when a delegate is collected. I'll look into this further. Thanks.


  • dork

    Maybe this would be of interest:

    http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/default.aspx

    Best regards,
    Johan Stenberg



  • skuehner

    MS Johan Stenberg wrote:

    Maybe this would be of interest:

    http://msdn.microsoft.com/msdnmag/issues/03/12/LeaseManager/default.aspx

    Best regards,
    Johan Stenberg

    Johan, you nailed it! Remoting objects are created with a default lease time of five minutes. Apparently, if an object is inactive for a duration longer than its lease time, it gets collected. This vital detail has escaped me until now.

    For people working with remoting and shared objects, I'll share this bit of code that demonstrates creating a shared object used with IpcChannel remoting and how to change its lease time from the default (five minutes) to one day (24 hours):

    BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

    BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();

    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

    System.Collections.Hashtable properties = new System.Collections.Hashtable();

    properties["name"] = servertName

    properties["portName"] = serverPortName;

    ipcChannel = new IpcChannel(properties, clientProv, serverProv);

    ChannelServices.RegisterChannel(ipcChannel, false);

    RemotingConfiguration.RegisterWellKnownServiceType(typeof(SharedObjects), serverServiceName, WellKnownObjectMode.Singleton);

    // Create the shared object to be used with remoting

    sharedObjects = (SharedObjects)Activator.GetObject(typeof(SharedObjects), serverServerURI);

    // Get the lease for the object

    ILease lease = (ILease)sharedObjects.GetLifetimeService();

    if (lease != null)

    {

    Debug.WriteLine("Initial lease time is " + lease.InitialLeaseTime);

    Debug.WriteLine("Current lease time is " + lease.CurrentLeaseTime);

    Debug.WriteLine("Renew on call time is " + lease.RenewOnCallTime);

    Debug.WriteLine("Sponsorship timeout is " + lease.SponsorshipTimeout);

    Debug.WriteLine("Current lease state is " + lease.CurrentState.ToString());

    // Change the least time to 1 day

    lease.Renew(TimeSpan.FromDays(1));

    Debug.WriteLine("Initial lease time is " + lease.InitialLeaseTime);

    Debug.WriteLine("Current lease time is " + lease.CurrentLeaseTime);

    Debug.WriteLine("Renew on call time is " + lease.RenewOnCallTime);

    Debug.WriteLine("Sponsorship timeout is " + lease.SponsorshipTimeout);

    Debug.WriteLine("Current lease state is " + lease.CurrentState.ToString());

    }


  • Event subscribers disappear after inactivity