Sunday, March 19, 2006

Issues when using MarshalByRefObject instances from several application domains

At first let’s consider why we need to inherit our classes from MarshalByRefObject.
The reason is very simple - we want use them in separate application domains.

Let’s suppose we have to appdomains: appdomain1 and appdomain2.
(In this post I will not cover the details of application domain creation)

public class MainAppD : MarshalByRefObject
{
public SlaveAppD slaveAppDomain;
public void DoInPrimaryAppDomain()
{
}
}

//this class will be executing on second app domain
public class SlaveAppD : MarshalByRefObject
{
public MainAppD mainAppDomain;
public void DoInSlaveAppDomain()
{
}
}

What's wrong with these classes?

Recently I had similar scenario, and wondered why did my objects get disconnected from other appdomain.
When object is disconnected and you try to call its methods you get RemotingException...

Let’s consider lifetime of the above mentioned
class members that are references, namely SlaveAppD.slaveAppDomain and MainAppD.mainAppDomain
will become __TransparentProxy references. All calls will go through these transparent proxies.

Notions of proxies and application domains are directly connected with notion lifetime.

If we will consider classes above neither of them cares about its lifetime.
MarshalByRefObject has InitializeLifetimeService() method that returns time lease. The lease specifies
how long this object can be "alive" (Basically this means that proxy connection is alive).
The default lease value is 5 minutes. To increase lifetime
one has to override InitializeLifetimeService. Lets set lease time to 15.

public override Object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromMinutes(15);
lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
}
return lease;
}

If you want infinite proxy connection lifetime the you simply return null.

//Infinite lifetime lease
public override Object InitializeLifetimeService()
{
return null;
}

Saturday, March 18, 2006

Blog connectivity

In order to stay always connected to this blog ( if I will change hosting ), please use this link for syndication link

Thursday, March 02, 2006

Beware of asynchronous methods calls that can complete synchronously. Part 1

In .NET every method can be executed asynchronously, it means that it will be executed in the separate thread, typically ThreadPool thread. Here is sample code…

class Program
{
public delegate void LongMethodDelegate();

static void Main(string[] args)
{
Console.WriteLine("Main thread: {0}",
Thread.CurrentThread.ManagedThreadId);

LongMethodDelegate @delegate =
new LongMethodDelegate(LongRunningMethod);

IAsyncResult ar = @delegate.BeginInvoke(
new AsyncCallback(OnComplete), null);
ar = @delegate.BeginInvoke(new AsyncCallback(OnComplete), null);
//@delegate.EndInvoke(ar);

Console.ReadLine();
}

static void LongRunningMethod()
{
Thread.Sleep(10000); //long running task
Console.WriteLine("--------- LongRunningMethod");
Console.WriteLine("Executing on thread: {0}",
Thread.CurrentThread.ManagedThreadId);
}

static public void OnComplete(IAsyncResult ar)
{
Thread thread = Thread.CurrentThread;

Console.WriteLine("--------- OnComplete");
Console.WriteLine("Completed on thread: {0}\n" +
"Synchronously: {1}\n" +
"ThreadPool thread: {2}\n" +
"IsBackground thread: {3}",
thread.ManagedThreadId,
ar.CompletedSynchronously.ToString(),
thread.IsThreadPoolThread.ToString(),
thread.IsBackground.ToString());
}
}

Everything is pretty simple here, LongRunningMethod() is executed on the separate thread, OnComplete is called when LongRunningMethod()is completed. The thread that completes the work is called WorkerThread.

While using this approach – method that is being called asynchornously will be executed on the separate thread… However, if you noticed IAsyncResult has CompletedSynchronously property. What for? It is a good question, and I hope soon it will be answered :8-)