Hi, I have the example. It is not perfect as an example, but i didn't have much time to do it. Succinctly, if you have an array with a MarshalByRefObject descendant, each one with a client manage by a different thread, remoting will be blocked if the servers call other servers all managed by different threads. This will not always happen, but if you increase the number of severs calling other servers after some number of threads this will happen almost for sure. In the example you can increase the constant UNITS and verify that after some value remoting communications will be blocked. To test the application, press button1 to start the threads responsible for the calls and then press button2 in order to verify if remoting is blocked.
Regards, Manuel using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Channels.Http; using System.Threading; namespace RemotingTest { #region Synchronizer component public class SynchronizerComp : MarshalByRefObject { private int count = 1; public void Wait() { lock(this) { while(count<=0) { Monitor.Wait(this,System.Threading.Timeout.Infinite); } count--; } } public void Release() { lock(this) { count++; Monitor.Pulse(this); } } } #endregion #region Class to register Test classes in a different application domain public class ServerCreator : MarshalByRefObject { public void RegisterURIsForRemoting(int NumbOfServers) { TcpChannel Channel = new TcpChannel(3000); ChannelServices.RegisterChannel(Channel); Type type = Type.GetType("RemotingTest.Test,RemotingTest"); //Register URIs for remoting for(int i = 0; i<NumbOfServers; i++) RemotingConfiguration.RegisterWellKnownServiceType(type,"Test" + i.ToString(),WellKnownObjectMode.Singleton); RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("RemotingTes t.SynchronizerComp,RemotingTest"),"Mutex",WellKnownObjectMode.Singleton); } } #endregion delegate void AsynchronousIncNeighbor(); public class Test : MarshalByRefObject { private long count = 0; private SynchronizerComp mutex; private Test[] neighbor = new Test[1024]; private AsynchronousIncNeighbor[] asynchronousIncNeighbor = new AsynchronousIncNeighbor[1024]; private long countNeighbors = 0; public void SetMutex(SynchronizerComp synchronizerComp) { mutex = synchronizerComp; } public void Increment(){ //All the instances of the Test class will increment their count one at a time if(mutex!=null) mutex.Wait(); count++; if(mutex!=null) mutex.Release(); } public long Count{get{return count;}} public long CountNeighbors{get{return countNeighbors;}} public Test Neighbor(int NeighborIndex){return neighbor[NeighborIndex];} public void AddNeighbor(Test Neighbor) { neighbor[countNeighbors] = Neighbor; asynchronousIncNeighbor[countNeighbors] = new AsynchronousIncNeighbor(neighbor[countNeighbors].Increment); countNeighbors++; } public void IncrementAllNeighbors() { for(int i = 0; i<countNeighbors; i++) asynchronousIncNeighbor[i].BeginInvoke(null,null); } public string HelloWorld { get{return "Hi there, remoting is working";} } } /// <summary> /// Summary description for Form1. /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; //########################################################################## ################# //########################################################################## ################# //########################################################################## ################# private const int UNITS = 2; //In my machine with 3 or more, remoting communications will be blocked //########################################################################## ################# //########################################################################## ################# //########################################################################## ################# private Test[] test = new Test[UNITS]; private Thread[] threadList = new Thread[UNITS]; private AppDomain domain = null; private SynchronizerComp mutex = null; public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(16, 16); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(144, 40); this.button1.TabIndex = 0; this.button1.Text = "Increment Neighbors"; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Location = new System.Drawing.Point(16, 64); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(144, 40); this.button2.TabIndex = 1; this.button2.Text = "Test if remoting is working"; this.button2.Click += new System.EventHandler(this.button2_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(176, 117); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.button2, this.button1}); this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } private int threadIndex; private void IncrementNeighbors() { Test t; lock(this) { t = test[threadIndex]; threadIndex++; } for(int i = 0; i<10; i++) t.IncrementAllNeighbors(); } private void DoCalls() { //Start incrementing neighbors for(int i = 0; i<test.Length; i++) { threadList[i] = new Thread(new ThreadStart(IncrementNeighbors)); threadList[i].IsBackground = true; threadList[i].Start(); } } private void MultithreadCallAndWait() { threadIndex = 0; DoCalls(); //Wait for the end of all threads for(int i = 0; i<test.Length; i++) { threadList[i].Join(); } } private void button1_Click(object sender, System.EventArgs e) { //Activate the process by pressing this button //Add neighbors if(test[0].CountNeighbors==0) for(int i = 0; i<test.Length; i++) { for(int ii = 0; ii<test.Length; ii++) if(i!=ii) test[i].AddNeighbor(test[ii]); } //Start increment neighbors Thread t = new Thread(new ThreadStart(MultithreadCallAndWait)); t.IsBackground = true; t.Start(); } private void button2_Click(object sender, System.EventArgs e) { //After pressing button 1, try to press this one //try to access one of the servers MessageBox.Show(test[0].HelloWorld); } private void Form1_Load(object sender, System.EventArgs e) { //Create a new domain to host Test instances domain = AppDomain.CreateDomain("Remoting Test"); ServerCreator creator = (ServerCreator)domain.CreateInstanceAndUnwrap("RemotingTest","RemotingTest.S erverCreator"); //Register Test URIs creator.RegisterURIsForRemoting(test.Length); int cNumber = 3000; //Get a proxy to the "mutex" mutex = (SynchronizerComp)Activator.GetObject(typeof(RemotingTest.SynchronizerComp), "tcp://localhost:" + cNumber + "/mutex"); //Create proxies for(int i = 0; i<test.Length; i++) { test[i] = (Test)Activator.GetObject(typeof(RemotingTest.Test),"tcp://localhost:" + cNumber + "/Test" + i.ToString()); test[i].SetMutex(mutex); } } } } You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com.