[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.remoting

Sharing a hashtable with .net remoting

Stephane

8/27/2004 12:35:00 PM

Hi,

I have a C# server working as a service using MarshalByRefObject
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecN...).

I only have one instance of the main server. This instance has a hashtable
containing my customers list. From an ASP.net web page, I call this server to
retreive that list, which is working fine.

However, I can't insert a new element. The weird thing is that the new
element is inserted but it desappear soon after.

Here's the configuration file for my server:

<configuration>
<system.runtime.remoting>
<application name="LiveSnapService">
<lifetime
leaseTime = "15M"
sponsorshipTimeOut = "10M"
renewOnCallTime = "15M"
pollTime = "10S" />
<service>
<wellknown type="LiveSnapDotNet.server.MainServer, LiveSnapDotNet"
objectUri="LiveSnapDotNet.server.MainServer"
mode="Singleton" />
</service>
<channels>
<channel ref="tcp" port="8085">
<serverProviders>
<formatter ref="binary" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

In the MainServer class, I have a static method which is returning the main
server reference which I use to communicate with the remote server (it's
calling itself in a sense).

It goes like this:

public static MainServer Instance
{
get
{
MainServer mainServerRef = null;
try
{
// Checks if it's already registered
if (ChannelServices.RegisteredChannels.Length == 0)
{
BinaryServerFormatterSinkProvider srvFormatter = new
BinaryServerFormatterSinkProvider();
srvFormatter.TypeFilterLevel = TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clntFormatter =
new BinaryClientFormatterSinkProvider();

IDictionary props = new HashTable();
props["port"] = 0;

TcpChannel chan = new TcpChannel(props, clntFormatter, srvFormatter);

ChannelServices.RegisterChannel(chan);
}
// Creates the server reference.
mainServerRef = (MainServer)Activator.GetObject(
typeof(LiveSnapDotNet.server.MainServer),
"tcp://localhost:8085/LiveSnapDotNet.server.MainServer");
}
catch(Exception e)
{
}
return mainServerRef;
}
}

Then, if I get the customers list, it works:

mainServer = MainServer.Instance;
mainServer.CustomersList.Count; // Gives the correct number, let's say 2

But if I try to insert an element:

mainServer.CustomersList.add(1,new Customer());
mainServer.CustomersList.Count;

This gives the previous number, 2 while it is supposed to be 3.

I also created a new method update(customer c) that add the element and
return the updated hashtable. This time, by doing this, I got the updated
hashtable:

mainServer.CustomersList.update(new Customer()).Count // This gives 3

But right after, mainServer.CustomersList is still a the same point as
before with 2 elements.

Why is the client hashtable not updated?

Thanks,

Stephane
1 Answer

Ken Kolda

8/27/2004 3:17:00 PM

0

It sounds like you have marked your CustomersList class as Serializable
instead of deriving it from MarshalByRefObject. When an object is not
derived from MarshalByRefObject, it has "pass-by-value" semantics when
crossing a remoting interface. In other words, when you have the line of
code

mainServer.CustomerList

your server serializes the CustomerList object and your client deserializes
it into a locally held copy. Thus, any operations you perform on that object
will never affect the copy held on the server -- you're only updating the
copy on the client. So, look at your code again:

// This line fetches a local copy of the Customer List from the server and
adds a new element to it
// Note that this does NOT affect the CustomerList on the server
mainServer.CustomersList.add(1,new Customer());

// Now, you're fetching a SECOND local copy of the customer list. That's why
your Count doesn't show
// that the element's been added -- because the list you're using in this
call is a different local copy then the
// list you used in the last call.
mainServer.CustomersList.Count;

This is something you need to be very aware of with remoting when using
Serializable classes. If you want to have your changes affect the object on
the server, then you need to derive your CustomerList class from
MarhsalByRefObject. This will cause the class to have "pass-by-reference"
semantics for remoting. However, if CustomerList is a Hashtable (or a class
that derives from Hashtable), then you'll need to create your own wrapper
class since Hashtable does not derive from MarshalByRefObject.

Ken


"Stephane" <Stephane@discussions.microsoft.com> wrote in message
news:29E2753B-3BB8-4BFE-85C2-B2C807E00F3B@microsoft.com...
> Hi,
>
> I have a C# server working as a service using MarshalByRefObject
>
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/...
tml/SecNetHT15.asp).
>
> I only have one instance of the main server. This instance has a hashtable
> containing my customers list. From an ASP.net web page, I call this server
to
> retreive that list, which is working fine.
>
> However, I can't insert a new element. The weird thing is that the new
> element is inserted but it desappear soon after.
>
> Here's the configuration file for my server:
>
> <configuration>
> <system.runtime.remoting>
> <application name="LiveSnapService">
> <lifetime
> leaseTime = "15M"
> sponsorshipTimeOut = "10M"
> renewOnCallTime = "15M"
> pollTime = "10S" />
> <service>
> <wellknown type="LiveSnapDotNet.server.MainServer, LiveSnapDotNet"
> objectUri="LiveSnapDotNet.server.MainServer"
> mode="Singleton" />
> </service>
> <channels>
> <channel ref="tcp" port="8085">
> <serverProviders>
> <formatter ref="binary" />
> </serverProviders>
> </channel>
> </channels>
> </application>
> </system.runtime.remoting>
> </configuration>
>
> In the MainServer class, I have a static method which is returning the
main
> server reference which I use to communicate with the remote server (it's
> calling itself in a sense).
>
> It goes like this:
>
> public static MainServer Instance
> {
> get
> {
> MainServer mainServerRef = null;
> try
> {
> // Checks if it's already registered
> if (ChannelServices.RegisteredChannels.Length == 0)
> {
> BinaryServerFormatterSinkProvider srvFormatter = new
> BinaryServerFormatterSinkProvider();
> srvFormatter.TypeFilterLevel = TypeFilterLevel.Full;
> BinaryClientFormatterSinkProvider clntFormatter =
> new BinaryClientFormatterSinkProvider();
>
> IDictionary props = new HashTable();
> props["port"] = 0;
>
> TcpChannel chan = new TcpChannel(props, clntFormatter,
srvFormatter);
>
> ChannelServices.RegisterChannel(chan);
> }
> // Creates the server reference.
> mainServerRef = (MainServer)Activator.GetObject(
> typeof(LiveSnapDotNet.server.MainServer),
> "tcp://localhost:8085/LiveSnapDotNet.server.MainServer");
> }
> catch(Exception e)
> {
> }
> return mainServerRef;
> }
> }
>
> Then, if I get the customers list, it works:
>
> mainServer = MainServer.Instance;
> mainServer.CustomersList.Count; // Gives the correct number, let's say 2
>
> But if I try to insert an element:
>
> mainServer.CustomersList.add(1,new Customer());
> mainServer.CustomersList.Count;
>
> This gives the previous number, 2 while it is supposed to be 3.
>
> I also created a new method update(customer c) that add the element and
> return the updated hashtable. This time, by doing this, I got the updated
> hashtable:
>
> mainServer.CustomersList.update(new Customer()).Count // This gives 3
>
> But right after, mainServer.CustomersList is still a the same point as
> before with 2 elements.
>
> Why is the client hashtable not updated?
>
> Thanks,
>
> Stephane