Hey Sunny,
I thought this trick of returning null from InitializeLifetimeService() in
the MBR object disabled it. The child object certainly
has this override. The child object is not a CAO. The server creates it,
the client simply gains access to it from the root object.
In my test project I follow this same pattern: I marshal a root object which
creates a child and the client accesses both of them.
Here is my test program...which I hesitate to put out here, because the test
program works!
This is the server...
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
using RemotingObjects;
namespace RemotingTestServer
{
class Server : MarshalByRefObject
{
static void Main(string[] args)
{
BinaryServerFormatterSinkProvider serverProv = new
BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel =
System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProv = new
BinaryClientFormatterSinkProvider();
IDictionary props = new Hashtable();
props["port"] = 1000;
TcpChannel tcpChannel = new TcpChannel(props, clientProv, serverProv);
ChannelServices.RegisterChannel(tcpChannel);
TopLevelClass topLevel = new TopLevelClass();
topLevel.Log("Marshaling the object.");
RemotingServices.Marshal((MarshalByRefObject) topLevel, "TopLevel",
typeof(TopLevelClass));
topLevel.Log("Marshaled.");
Thread.Sleep(Timeout.Infinite);
}
}
}
---------------------------------------------------------------
This is the client...
using System;
using RemotingObjects;
namespace RemotingTestClient
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
TopLevelClass toplevel =
(TopLevelClass)Activator.GetObject(typeof(TopLevelClass),"tcp://localhost:10
00/TopLevel");
toplevel.Log("Activated toplevel.");
ChildClass child = toplevel.child;
child.Log("Referenced child.");
int sleeptime = 5000;
while(true)
{
// toplevel.Log("Hello toplevel, sleeping " + sleeptime/1000 + " sec.");
child.Log("Hello child, sleeping " + sleeptime/1000 + " sec.");
System.Threading.Thread.Sleep(sleeptime);
sleeptime *= 2;
}
}
public static void Log(string message)
{
Console.WriteLine(DateTime.Now.ToString() + "\t- " + message);
}
}
}
---------------------------------------------------------
These are the root and child objects...
using System;
namespace RemotingObjects
{
public class TopLevelClass : MarshalByRefObject
{
public ChildClass child;
public TopLevelClass()
{
child = new ChildClass();
}
public void Log(string message)
{
Console.WriteLine(DateTime.Now.ToString() + "\t(TopLevel) " + message);
}
public override object InitializeLifetimeService()
{
return null;
}
}
public class ChildClass : MarshalByRefObject
{
public void Log(string message)
{
Console.WriteLine(DateTime.Now.ToString() + "\t(Child) " + message);
}
public override object InitializeLifetimeService()
{
return null;
}
}
}
---------------------------------------------------
Lifetime services never kills the child even as the delay between accesses
approaches one hour. Again, the test program works and my real program
doesn't. Either I am overlooking something or the problem occurs when the
server-size tree of objects become large (about 20 or 30 objects in my
case).
Regards,
Bob Rundle
Sam Santiago - 28 Jul 2004 23:46 GMT
Any MBR object created indirectly by an SAO and returned to a client is a
CAO by default for remoting. Sounds like you will have to use a sponsor:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cp
conrenewingleases.asp
Although what your are doing should work in theory ;-).

Signature
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTechture.com
_______________________________
> Hey Sunny,
>
[quoted text clipped - 58 lines]
> {
> TopLevelClass toplevel =
(TopLevelClass)Activator.GetObject(typeof(TopLevelClass),"tcp://localhost:10
> 00/TopLevel");
> toplevel.Log("Activated toplevel.");
[quoted text clipped - 61 lines]
> Regards,
> Bob Rundle
Sunny - 29 Jul 2004 14:52 GMT
Hi Bob,
most probably you are overlooking something. Try to add functionality to
your test program until it stops working, or try to start stripping down
your main program until the problem disappear.
Sunny
> Hey Sunny,
>
[quoted text clipped - 124 lines]
> Regards,
> Bob Rundle
Bob Rundle - 29 Jul 2004 15:15 GMT
Sunny,
Yes I had overlooked something. It turns out the problem is the event
wrapper. I examined the call stack for the error and I discovered that the
"Requested Service Not Found" is not the child object in the server but the
event wrapper the child is trying to call back in the client!
So I have added the InitializeLifetimeService() override returning null in
the event wrapper and I think this will take care of this problem. Although
I am starting to think that InitializingLifetimeServices() to null everwhere
is not the best course of action. However it is not clear to me what the
appropriate design pattern is when remoting events are involved.
It also seems that I need some try blocks around the code which raise the
remote events. I had thought that problems created by raising events where
silently caught, but apparently I am wrong about this.
Regards,
Bob Rundle
> Hi Bob,
>
[quoted text clipped - 66 lines]
> > {
> > TopLevelClass toplevel =
(TopLevelClass)Activator.GetObject(typeof(TopLevelClass),"tcp://localhost:10
> > 00/TopLevel");
> > toplevel.Log("Activated toplevel.");
[quoted text clipped - 61 lines]
> > Regards,
> > Bob Rundle
Sunny - 29 Jul 2004 22:50 GMT
Hi Bob,
> I am starting to think that InitializingLifetimeServices() to null everwhere
> is not the best course of action. However it is not clear to me what the
> appropriate design pattern is when remoting events are involved.
Create a sponsor at the client. Attach that sponsor to the wrapper
object at the client. And dettach it, when you are done with the
connection. This way, the wrapper will live while you need it. Using
null everywhere is not good :)
Sunny