Hope someone helps me with this
If CallbackHandler.proxy
is static, then everything works fine:
using System;
using System.ServiceModel;
namespace ConsoleApplication5
{
// Define class which implements callback interface of duplex contract
public class CallbackHandler : ServiceReference1.IStockServiceCallback
{
public static InstanceContext site = new InstanceContext(new CallbackHandler());
public static ServiceReference1.StockServiceClient proxy = new ServiceReference1.StockServiceClient(site);
// called from the service
public void PriceUpdate(string ticker, double price)
{
}
}
class Program
{
static void Main(string[] args)
{
CallbackHandler cbh = new CallbackHandler();
}
}
}
But if I declare it as an instance member, then I get System.TypeInitializationException: The type initializer for CallBackHandler’ threw an exception. ---> System.ArgumentNullException. Value cannot be null exception
using System;
using System.ServiceModel;
namespace ConsoleApplication5
{
// Define class which implements callback interface of duplex contract
public class CallbackHandler : ServiceReference1.IStockServiceCallback
{
public static InstanceContext site = new InstanceContext(new CallbackHandler());
public ServiceReference1.StockServiceClient proxy = new ServiceReference1.StockServiceClient(site);
// called from the service
public void PriceUpdate(string ticker, double price)
{
}
}
class Program
{
static void Main(string[] args)
{
CallbackHandler cbh = new CallbackHandler();
}
}
}
Any idea why making CallbackHandler.proxy
an instance member throws an exception?
EDIT:
In the 2nd case, the instance constructor in the line marked (*) runs before the completion of the static constructor (yes, it's possible), but at that point site is still not assigned.
Thus in second case site
should be initialized to null, while in first case it should be assigned a non-null value?!
But…
At first I thought static site
was null ( regardless of whether proxy
was instance or static member ) simply because it was initialized with CallbackHandler
, as explained here:
So when CLR tries to instantiate an instance
O
( which it would then assign tosite
), it waits for static fieldsite
to get initialized, whilesite
waits forO
to get created, which in turn would initializesite
field. Since this could create a deadlock of sort,site
is “the wiser” and thus gets set to default value null?!
Then I remembered that site
is not null if proxy
is also static, so my understanding of what’s happening changed to:
So when CLR tries to instantiate an instance
O
( which it would then assign tosite
), it waits for static fieldsite
to get initialized ( so that it can assignsite’s
reference to its instance memberproxy
). whilesite
waits forO
to get created, which in turn would initializesite
field. Since this could create a deadlock of sort, CLR detects this potential deadlock and setssite
to null.
But then I’ve run your test code and for some reason site
is assigned ( thus is not null ) even if proxy
is not static:
using System;
namespace ConsoleApplication5
{
public class InstanceContext
{
public InstanceContext(CallbackHandler ch)
{
Console.WriteLine("new InstanceContext(" + ch + ")");
}
}
public class StockServiceClient
{
public StockServiceClient(InstanceContext ic)
{
Console.WriteLine("new StockServiceClient(" + ic + ")");
}
}
// Define class which implements callback interface of duplex contract
public class CallbackHandler
{
public static InstanceContext site = new InstanceContext(new CallbackHandler());
public StockServiceClient proxy = new StockServiceClient(site);
public CallbackHandler()
{
Console.WriteLine("new CallbackHandler()");
}
static CallbackHandler()
{
Console.WriteLine("static CallbackHandler()");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(CallbackHandler.site == null); // returns false
}
}
}
What is going on?