This message was discovered on microsoft.public.dotnet.distributed_apps.
Responses highlighted in red are from those people who are likely to be able to contribute good, authoratitive information to this discussion. They include Microsoft employees, MVP's and others who IMHO contribute well to these kinds of discussions.
| Chun Fan (VIP) |
hi, there,
I am recently using .net remoting to develop a distributed application and some synchronization problem bothered for a long time.
The problem looks as following: There is one server application that hosts a remote object, "mydata". This remote object is configured as a singlton object. Three functions are developed within this object to provide synchronized data access: public class MyData :MarshalByRefObject{
.... public void Lock(){ System.Threading.Monitor.Enter(this); }
public void Release(){ System.Threading.Monitor.Exit(this); }
public bool TryLock(){ return System.Threading.Monitor.TryEnter(this); } .... }
And two client applications with similar behavior that at first, each client application tries to obtain the lock on mydata by invoking mydata.Lock(); then does some processing. After the processing is done, the client will display a message box by invoking 'MessageBox.show()' and waiting for user's input. After the user's input is received, the client will invoke mydata.Release() to release the lock on mydata such that other clients may be able to access mydata.
So I started the first client. The client obtained the lock and displayed the message box, waiting for my input. Then the second client was started. If everything were working, the second client should have been blocked since it can not obtain the lock. Unfortunately, the second client just went on as if it had got the lock and also displays the message box!
The more wierd thing was that after a random length of time(several minutes to hours), the lock could work!, i.e. before one client releases the lock, the other one is blocked at the mydata.Lock() invocation!
So could anybody help me to tell me what's wrong here? Or anybody can tell me how to implment such a locking in the .net remoting? Thanks a lot! -- Sincerely
Chun
|
|
|
| |
|
|
| |
| |
| Chun Fan (VIP) |
More information I got: If I do nothing after starts the client, i.e. not trying to access the remote object, for several minutes, the blocking mechanism works smoothly. Anyone can give me a hand to let me know what's wrong here? Is that my program error or a bug of .net framework? Thanks a lot!
"Chun Fan" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| Sam Santiago |
What are you doing within your Singleton object that you need synchronization? I do not think it's a good idea to have your clients control the synchronization, especially via a remote method call. This pushes the responsibility of synchronization management to the client which assumes all your clients will be coded properly. A single badly coded client could cause your entire server object to become unusable by any other clients - too big a risk.
I recommend having the synchronization management done strictly server side. Your clients should simply acquire a reference to your Singleton an execute the needed method. Your Singlton should on the server side within the methods that need synchronization use a Monitor to synchronize the appropriate activity.
Lastly, if you want a true Singleton be sure to override the InitializeLifetimeService method provided from the MarshalByRefObject to return null. Some of the behavior you're observing might be due to the fact that your object's lifetime lease has expired (5 min default from the last method call) and a new object is created when you invoke your SAO after a few minutes.
Thanks,
Sam
-- _______________________________ Sam Santiago Click here to reveal e-mail address http://www.SoftiTechture.com _______________________________ "Chun Fan" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Chun Fan (VIP) |
Thanks for your answer. If the client doesn't need to acquire several different locks on different remote objects before performing any real processing work, it is a good idea to control the syncrhonization strictly on the server side. Actually, I am implementing a two-phase locking like application. So at the first phase, the client should acquire all the locks (which may on different remote objects), then the client can perform some processing at its side, after that, the client should release all the locks have been acquired. The locks may on different server/remote objects so it is necessary for the client to control the lock. However, the actual locks are on the server side.
Secondly, the InitializeLifetimeService method has been overrided to return null and that didn't solve the problem.
And now the problem is that if I do NOTHING after the clients start, after 2 ~ 5 minutes, the blocking mechanism works smoothly. However, if I let the clients access the remote objects from the beginning, the blocking doesn't work. And if I stop allowing the clients to access the remote objects for a while, the blocking can work again. So any suggestions to solve this? Thanks a lot! "Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| Sam Santiago |
If you can post some code that would probably make things more clear. Have you considered how you would handle deadlocks? If you need distributed transactions you might consider EnterpriseServices vs. trying to implement your own locking mechanism.
Thanks,
Sam
-- _______________________________ Sam Santiago Click here to reveal e-mail address http://www.SoftiTechture.com _______________________________ "Chun Fan" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
| |
| |
| Chun Fan (VIP) |
Actually, the related server side object code has been posted. The following is the related client side code:
public class Client { .... mydata = new MyData(); // MyData is a remote singleton object on the server .... mydata.Lock(); ... // acquire other locks and do some processing mydata.Release(); .... }
What we are trying to do is to demonstrate the two-phase locking and two-phase committment using .Net. I am not familiar with .net's enterprise services so I do not know if it allows me to do things like this: acquire all the locks before doing processing and then release all the locks. Any suggestions? thanks a lot!
"Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| Sam Santiago |
You might want to read this article:
HOW TO: Perform a Distributed Transaction with a .NET Provider by Using ServicedComponent in Visual Basic .NET http://support.microsoft.com/default.aspx?scid=kb;en-us;316627
You might want to read up on Enterpise Services: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/entserv.asp
Thanks,
Sam
-- _______________________________ Sam Santiago Click here to reveal e-mail address http://www.SoftiTechture.com _______________________________ "Chun Fan" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... > Actually, the related server side object code has been posted. The following [Original message clipped]
|
|
|
| |
|
| |
| |
| Chun Fan (VIP) |
Let me take a look. Thanks a lot!
"Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
|
| |
| Chun Fan (VIP) |
The articles are good. but I am now wondering why the simplest, the most straight forward way can not work as expected. As I have said, only if I do not use the clients to access the remote object, everything works just find and smoothly. So how come they work like this? Thanks!
"Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| Sam Santiago |
Without posting detailed code snippets showing how you configure remoting and your server and client objects it's difficult to say. I think the main point is that there are many other complicating issues to think about that Enterprise Services addresses.
Thanks,
Sam
-- _______________________________ Sam Santiago Click here to reveal e-mail address http://www.SoftiTechture.com _______________________________ "Chun Fan" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
| |
| |
| Chun Fan (VIP) |
/// remote object code [Serializable] public class Data_2:MarshalByRefObject { public Data_2() { m_nID = 2; m_nOwnerActorID = 1; m_strName = "Data 2"; dataValueString = ""; dataType = ""; obj = new object(); mutex = new System.Threading.Mutex(true); }
public bool TryLock() { // return mutex.WaitOne(100, true); return System.Threading.Monitor.TryEnter(this); }
public void Lock() { // mutex.WaitOne(); System.Threading.Monitor.Enter(this); }
public void Release() { // mutex.ReleaseMutex();
System.Threading.Monitor.Pulse(this); System.Threading.Monitor.Exit(this); } public object obj; public System.Threading.Mutex mutex; }
/// server code public class RemoteLoader: MarshalByRefObject { public RemoteLoader() { m_arrDatas = new ArrayList(); m_arrAssemblies = new ArrayList(); }
public void LoadAvailableDatas() { string[] DataFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
foreach (string filename in DataFiles) { Assembly a = Assembly.LoadFrom(filename); m_arrAssemblies.Add(a); } RemotingConfiguration.Configure( @"..\..\server.exe.config" ); }
public int Length { get {return m_arrDatas.Count;} }
private ArrayList m_arrAssemblies;
private ArrayList m_arrDatas; }
/// server configuration file <configuration> <system.runtime.remoting> <application name="Server"> <service> <wellknown mode="Singleton" type="ConcreteData.Data_2, ConcreteACDATE" objectUri="Data_2_URI" /> <channels> <channel ref="http" port="8080" /> <channel ref="tcp" port="8081" /> </channels> </application> </system.runtime.remoting> </configuration>
/// client code /// have been shown in previous posts:)
/// client configuration <configuration> <system.runtime.remoting> <application name="Client"> <client> <wellknown type="ConcreteACDATE.Data_2, ConcreteACDATE" url="tcp://localhost:8081/Data_2_URI" /> </client> <channels> <channel ref="tcp" port="0"> <clientProviders> <formatter ref="binary" /> </clientProviders> <serverProviders> <formatter ref="binary" typeFilterLevel="Full" /> </serverProviders> </channel> </channels> </application> </system.runtime.remoting> </configuration>
Is that detailed enough? Thanks a lot!
Chun
"Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
| |
| Sam Santiago |
I don't know what's going on, but I don't believe the Monitor object will help you create a distributed application object lock. Monitor will allow 1 thread to lock an object, preventing other threads from accessing it. But you are not in control of the threads that access your remote object - it's all handled by the remoting infrastructure. In fact, there is no guarantee that the same thread services all requests for the same client. You would have to write a application level locking mechanism that would "lock" your remote object and keep track of which client owns that lock. You would have to synchronize within your methods that acquire and release your application lock, so Monitor could help there. Good luck.
Thanks,
Sam
-- _______________________________ Sam Santiago Click here to reveal e-mail address http://www.SoftiTechture.com _______________________________ "Chun Fan" <Click here to reveal e-mail address> wrote in message news:Click here to reveal e-mail address... [Original message clipped]
|
|
|
| |
|
|
| |
| |
| Chun Fan (VIP) |
| GOOD ANSWER |
got it. thanks:)
"Sam Santiago" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
| Chun Fan (VIP) |
For one more thing, I am using VS.net 2003 pro and Windows XP running one a P4 desktop. Thanks!
"Chun Fan" wrote:
[Original message clipped]
|
|
|
| |
|
|
| |
|
|
|
|
|