My task needs to load an assembly. How do I release the lock on the assembly once my task is done?
By default, the ""MSBuild"" engine consists of only a single ""AppDomain"", and all tasks run within this single ""AppDomain"". What this means is that once a task does an Assembly.Load or
Assembly.LoadFrom on a particular assembly on disk, that assembly will be locked for the duration of the ""AppDomain"". For IDE builds in particular, the main ""AppDomain"" doesn't get destroyed until the whole IDE shuts down. So if you try to do a build from the IDE, you will find that subsequent builds may fail due to the assembly still being locked by the task from the first build.
The fix for this is in the task that is loading the assembly. The task must mark itself specially in order for ""MSBuild"" to load it into its own ""AppDomain"". That way, when the task is complete, the ""AppDomain"" in which the assembly was loaded will be destroyed and the lock on the assembly will be released.
Beta 1
In order for a task to mark itself to be loaded in a separate ""AppDomain"", it needs to do two things:
- Inherit from "TaskMarshalByRef" instead of just "Task".
- Add the ""LoadInSeparateAppDomain"" attribute to the task class.
Here's an example:
[LoadInSeparateAppDomain]
public sealed class [MyTaskWhichLoadsAnAssembly] : [TaskMarshalByRef]
{
public override bool Execute()
{
...
}
}
Beta 2 and Beyond
In order for a task to mark itself to be loaded in a separate ""AppDomain"", it needs to do one thing:
- Inherit from "AppDomainIsolatedTask" instead of just "Task".
Here's an example:
public sealed class [MyTaskWhichLoadsAnAssembly] : [AppDomainIsolatedTask]
{
public override bool Execute()
{
...
}
}