Executing code in a new application domain

April 8, 2012 2 comments

A coworker recently mentioned a scenario where he needs to use legacy code in a multi-threaded environment. The class in-question is written in such a way that it holds state and needs to be reset before the class itself can be used again, therefore preventing it from being used in multiple threads at the same time. Although it may not be the most efficient method, we can create a new application domain for each thread and execute the code in there.

Just prototyping out some ideas, an API like this may be useful:

NewAppDomain.Execute(() =>
{
	// Run code in here
});

Each call to Execute would create a new application domain.

AppDomain domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

To execute our Action that we’re passing to the Execute method, we’ll need to create a new instance of Action in our new application domain. However, trying to call the CreateInstanceAndUnwrap method on the new application domain will throw an exception:

Unhandled Exception: System.MissingMethodException: Constructor on type 'System.Action' not found.

Instead, we’ll need to create a new class that can be instantiated in the new application domain. This new class AppDomainDelegate will act as a delgate and execute the Action that we pass to it.

public static class NewAppDomain
{
    public static void Execute(Action action)
    {
        AppDomain domain = null;

        try
        {
            domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

            var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
                typeof(AppDomainDelegate).Assembly.FullName,
                typeof(AppDomainDelegate).FullName);

            domainDelegate.Execute(action);
        }
        finally
        {
            if (domain != null)
                AppDomain.Unload(domain);
        }
    }

    private class AppDomainDelegate : MarshalByRefObject
    {
        public void Execute(Action action)
        {
            action();
        }
    }
}

Now we can use this class to execute code in another application domain.

NewAppDomain.Execute(() =>
{
    Console.WriteLine("Hello World");
});

Parameters

Trying to use variables declared outside the scope of the lambda will throw a serialization exception.

int i = 0;

NewAppDomain.Execute(() =>
{
	Console.WriteLine("Hello World " + i);
});

We can update the code to receive parameters across application domains by adding an overload for the Execute method:

public static class NewAppDomain
{
    public static void Execute(Action action) { ... }

    public static void Execute<T>(T parameter, Action<T> action)
    {
        AppDomain domain = null;

        try
        {
            domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

            var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
                typeof(AppDomainDelegate).Assembly.FullName,
                typeof(AppDomainDelegate).FullName);

            domainDelegate.Execute(parameter, action);
        }
        finally
        {
            if (domain != null)
                AppDomain.Unload(domain);
        }
    }

    private class AppDomainDelegate : MarshalByRefObject
    {
        public void Execute(Action action) { ... }

        public void Execute<T>(T parameter, Action<T> action)
        {
            action(parameter);
        }
    }
}

Now we can pass parameters to the method. We’ll need to make sure that any parameters we pass are marked as Serializable since they will be serialized and deserialized across application domains.

int i = 0;

NewAppDomain.Execute(i, x =>
{
    Console.WriteLine("Hello World " + x);
});

Returning Results

In cases where we want the Execute method to return results, we can add two additional method overloads that use Func<T> instead of Action:

public static T Execute<T>(Func<T> action)
{
    AppDomain domain = null;

    try
    {
        domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

        var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
            typeof(AppDomainDelegate).Assembly.FullName,
            typeof(AppDomainDelegate).FullName);

        return domainDelegate.Execute(action);
    }
    finally
    {
        if (domain != null)
            AppDomain.Unload(domain);
    }
}

public static TResult Execute<T, TResult>(T parameter, Func<T, TResult> action)
{
    AppDomain domain = null;

    try
    {
        domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

        var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
            typeof(AppDomainDelegate).Assembly.FullName,
            typeof(AppDomainDelegate).FullName);

        return domainDelegate.Execute(parameter, action);
    }
    finally
    {
        if (domain != null)
            AppDomain.Unload(domain);
    }
}

… and the same overloads for the delegate class AppDomainDelegate:

public T Execute<T>(Func<T> action)
{
    return action();
}

public TResult Execute<T, TResult>(T parameter, Func<T, TResult> action)
{
    return action(parameter);
}

We can now get results back. We’ll need to make sure that any results we return are marked as Serializable.

Result first = NewAppDomain.Execute(() => new Result());
Result second = NewAppDomain.Execute(parameter, x => new Result());

Using The Class

The entire class can be found here. To demonstrate, we’ll create a class that uses a public static field as a counter.

public class SharedClass : MarshalByRefObject
{
    public static int Counter = 1;

    public void Print()
    {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " - " + Counter);
        Counter++;
    }
}

We’ll call the Print method in another application domain using our NewAppDomain class:

NewAppDomain.Execute(() =>
{
	new SharedClass().Print();
	new SharedClass().Print();
});

NewAppDomain.Execute(() =>
{
	new SharedClass().Print();
	new SharedClass().Print();
	new SharedClass().Print();
	new SharedClass().Print();
});

The result:

New App Domain: 3ca2e6de-a5bd-40ef-b471-edb8c19024c2 - 1
New App Domain: 3ca2e6de-a5bd-40ef-b471-edb8c19024c2 - 2
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 1
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 2
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 3
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 4

If the application domain was the same, we would have seen the counter increment to 6. Notice that SharedClass inherits from MarshalByRefObject. If we instantiate a new instance of SharedClass and pass it as a parameter to our Execute method, this object is now shared across application domains via remoting. To demonstrate, we can use the Execute overload that takes a parameter:

var sharedClass = new SharedClass();

sharedClass.Print();
sharedClass.Print();

NewAppDomain.Execute(sharedClass, x => x.Print());

sharedClass.Print();

The result:

AppDomainDemo.exe - 1
AppDomainDemo.exe - 2
AppDomainDemo.exe - 3
AppDomainDemo.exe - 4

As expected, the counter did not reset. However, if we change SharedClass by removing MarshalByRefObject and marking the class as Serializable, we’ll see a different result:

AppDomainDemo.exe - 1
AppDomainDemo.exe - 2
New App Domain: b9404ee9-f4fc-4937-84ad-9d0369e36bb6 - 1
AppDomainDemo.exe - 3

Logging lambda expressions

March 30, 2012 Leave a comment

When working with lambda expressions, there are scenarios where I need to log when a Func<bool> returns false. In the example below, just logging “condition was not met” doesn’t give me very much information.

public void SomeMethod(Func<Person, bool> condition)
{
	if (!condition(person))
	{
		Log.Info("Condition was not met.");
		return;
	}

	// Do something
}

If I called the method like so:

obj.SomeMethod(x => x.Name == "Malvin");

… I would like to be able to turn that lambda expression into a meaningful string.

Unfortunately, there doesn’t appear to be an easy way to turn a lambda expression into a readable string. Instead, I had to use expression trees.

public void SomeMethod(Expression<Func<Person, bool>> expression)
{
	if (!expression.Compile()(person))
	{
		Log.Info("Condition was not met: " + expression);
		return;
	}

	// Do something
}

Now if I call the method and the condition fails, I should see:

Condition was not met: x => (x.Name == "Malvin")

However, expression trees are much more expensive than lambda expressions. Running a non-scientific benchmark on my Core i7 @ 3.2 GHz yields some fairly obvious results.

void Main()
{
	Stopwatch sw = Stopwatch.StartNew();
	
	for (int i = 0; i < 100000; i++)
		UsingExpression(() => false);
	
	sw.Stop();
	
	Console.WriteLine ("Expression: " + sw.ElapsedMilliseconds);
	
	sw.Restart();
	
	for (int i = 0; i < 100000; i++)
		UsingLambda(() => false);
		
	sw.Stop();
	
	Console.WriteLine ("Lambda: " + sw.ElapsedMilliseconds);
}

public void UsingExpression(Expression<Func<bool>> expression)
{
	if (expression.Compile()())
		Console.WriteLine ("hello world");
}

public void UsingLambda(Func<bool> condition)
{
	if (condition())
		Console.WriteLine ("hello world");
}

Output:

Expression: 4154
Lambda: 0

This may be a problem for high volume systems, but I don’t think the extra overhead will be an issue for most cases.

Casting and converting to strings

March 13, 2012 1 comment

One thing that makes me nervous while looking through a code base is the liberal use of the ToString() method everywhere. There are a couple different ways to convert/cast to a string:

Explicit cast:

string str = (string)someObj;

ToString() method:

string str = someObj.ToString();

Convert.ToString() method:

string str = Convert.ToString(someObj);

as operator:

string str = someObj as string;

Explicit casts should be used at times when you are sure that someObj is a string. It also doubles as an assertion since an InvalidCastException will be thrown at runtime if the cast fails. The result will be null if attempting to cast a null object.

The ToString() method returns the string representation of an object. If someObj is null, a NullReferenceException will be thrown.

The Convert.ToString() method behaves differently depending on the type of object passed to the method. When an object is passed to the method, it calls the ToString() method on the object:

public static string ToString(Object value) 
{
	return ToString(value, null);
} 

public static string ToString(Object value, IFormatProvider provider) 
{ 
	IConvertible ic = value as IConvertible; 
	
	if (ic != null)
		return ic.ToString(provider); 
		
	IFormattable formattable = value as IFormattable;
	
	if (formattable != null)
		return formattable.ToString(null, provider);
		
	return value == null ? String.Empty : value.ToString(); 
}

When a string is passed to the Convert.ToString(), it simply passes through:

public static String ToString(String value) 
{
	Contract.Ensures(Contract.Result<string>() == value);
	return value; 
}

This is important to remember because if a null object is passed to the Convert.ToString() method, an empty string is returned. However, if a null string is passed to the method, a null is returned.

The as operator provides a way to cast an object without throwing an exception if the cast fails. If a cast fails, the result will be null.

Stop calling people resources

March 11, 2012 Leave a comment

I tend to hear project managers or management in general use the term “resources” to describe people that work on a project. Over time, I’ve really grown to hate this word.

The problem with this mindset is that the word resource becomes synonymous with a piece of equipment that performs a monotonous action. This often translates to managers hiring less-experienced developers or outsourcing a project to the lowest bidder since this mindset promotes the idea that people are interchangeable resources. This often leads to incorrectly staffing a project or throwing “resources” at a project to meet a deadline. No, no, and no. People are complex and everyone is different. Two developers with similar skill sets will learn a new code base at different rates.

Resources are commodities that do not change. The cost of a project, tools, time, etc… are all resources that can be controlled. Applying the same presumptions to people will create a toxic environment.

Using the term “resources” to describe people is demeaning. People are not drones. People do not aspire to become a resource.

People will dedicate more energy to a project if you empower them to make a difference.

Finding number of rows and disk space in SQL Server

March 6, 2012 Leave a comment

To see how many rows a table contains or how much disk space a table is using, we can use the system stored procedure sp_spacedused to quickly return information about a table or the database.

For a single table, we can pass the table name to the stored procedure:

We can execute the stored procedure without passing a table name to see how much disk space the entire database is using:

We can combine this system stored procedure with the undocumented stored procedure sp_msforeachtable to view the number of rows and disk space usage for all tables in the current database:

However, we have to keep in mind that the numbers being reported by sp_spaceused may not be immediately accurate after an index or table has been dropped, a table has been truncated, etc… since the information is not maintained in real time. The command dbcc updateusage may be execute to update the information for a single table or the entire database. Similarly, the sp_spaceused stored procedure may be executed with an additional parameter to update the information for a single table or the entire database:

-- Single table
sp_spaceused @objname = 'Person.Address', @updateusage = 'true'

-- Entire database
sp_spaceused @updateusage = ‘true’

Although we’ve executed the update commands above, the row counts may still be inaccurate. The commands above only updates the disk space usage information, but not the row count information stored in the table sysindexes. We may execute the command dbcc updateusage with the count_rows argument to update sysindexes:

-- Single table
dbcc updateusage ('AdventureWorks', 'Person.Address') with count_rows

-- Entire database
dbcc updateusage (0) with count_rows

Castle Windsor – resolving collections

February 27, 2012 Leave a comment

Although I’ve used Castle Windsor on many projects, I often forget that Windsor does not automatically resolve dependencies that are a collection.

public class Demo
{
	private readonly IPrinter[] printers;

	public Demo(IPrinter[] printers)
	{
		this.printers = printers;
	}
}

Trying to call the Resolve method on the class above will throw an exception:

Castle.MicroKernel.Handlers.HandlerException: Can't create component 'CollectionResolverDemo.Demo' as it has dependencies to be satisfied.

'CollectionResolverDemo.Demo' is waiting for the following dependencies:
- Service 'CollectionResolverDemo.IPrinter[]' which was not registered.

Before registering components, we need to add a dependency resolver that can handle arrays, lists, and other collections:

container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

It is important to add the collection resolver before registering components. If the resolver is added after the component registration, collections will not be resolved correctly and the same exception will be thrown.

container.Register(Component.For<Demo>());
container.Register(Component.For<IPrinter>().ImplementedBy<RedPrinter>());
container.Register(Component.For<IPrinter>().ImplementedBy<GreenPrinter>());
container.Register(Component.For<IPrinter>().ImplementedBy<BluePrinter>());

// Bad
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

One strange behavior that I’ve noticed is that if I add the collection resolver in the middle of my registration:

container.Register(Component.For<Demo>());
container.Register(Component.For<IPrinter>().ImplementedBy<RedPrinter>());
container.Register(Component.For<IPrinter>().ImplementedBy<GreenPrinter>());

container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

container.Register(Component.For<IPrinter>().ImplementedBy<BluePrinter>());

I would expect that BluePrinter would be the only printer that is passed to the Demo class. However, this is not the case. Instead, the entire collection of IPrinters is resolved correctly.

Castle Windsor 3 – Classes and Types

February 7, 2012 Leave a comment

In my previous post on strongly typed sessions in ASP.NET, I had to manually look through the current assembly and retrieve all interfaces that end in “Session”. To register these interfaces with my container, I had to loop through each type found and register them one-by-one:

IEnumerable<Type> sessions =
    Assembly
        .GetExecutingAssembly()
        .GetTypes()
        .Where(x => x.IsInterface && x.Name.EndsWith("Session"));

foreach (Type session in sessions)
{
    Type sessionTemp = session;

    container.Register
    (
        Component
            .For(session)
            .UsingFactoryMethod(x =>
            {
                var factory = x.Resolve<DictionaryAdapterFactory>();
                return factory.GetAdapter<object>(sessionTemp, new SessionDictionary(HttpContext.Current.Session));
            })
            .LifeStyle.PerWebRequest
    );

Unfortunately, Castle Windsor 2.x did not have support for finding and registering interfaces with no implementions for use with a factory method or typed factories. I also couldn’t take advantage of the rich registration API of the AllTypes class since AllTypes only returned concrete classes.

Enter Castle Windsor 3. In version 3, Castle Windsor introduced two new registration classes, Classes and Types. The Classes class is identical to AllTypes. The new Types class returns all types, including interfaces, abstract classes, and concrete classes.

We can now update the registration code above to take advance of the new Types class:

container.Register
(
    Types
        .FromThisAssembly()
        .Where(t => t.IsInterface && t.Name.EndsWith("Session"))
        .Configure(c => c.UsingFactoryMethod(f =>
        {
            var factory = f.Resolve<DictionaryAdapterFactory>();
            return factory.GetAdapter<object>(c.Implementation, new SessionDictionary(HttpContext.Current.Session));
        })) 
        .LifestylePerWebRequest()
);

Follow

Get every new post delivered to your Inbox.