A
Andy
Hi,
I'm trying to create a pair of NAnt tasks so that I can syncronize
access to shared resources when two builds are running concurrently.
I run the two builds, the first aquires the mutex properly, sleeps ten
seconds, then releases it properly.
The second build correctly blocks when it hits WaitOne, but then throws
an AbandonedMutexException when the first build calls ReleaseMutex.
The thing is, the thread doesn't seem to be abandoned.
Here's the code.
[TaskName( "aquireLock" )]
public class AquireLock : Task {
#region Fields
[ThreadStatic]
internal static Mutex mutex;
private string lockName;
#endregion
#region Properties
[TaskAttribute( "resourceName",
Required = true, ExpandProperties = true)]
public string LockName {
get { return lockName; }
set { lockName = value; }
}
#endregion
#region Task overrides
/// <summary>Executes the task.</summary>
protected override void ExecuteTask() {
mutex = new Mutex( true, LockName );
Log(
Level.Info,
string.Format(
"Requesting lock: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
mutex.WaitOne();
Log(
Level.Info,
string.Format(
"Lock aquired: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
}
#endregion
}
[TaskName( "releaseLock" )]
public class ReleaseLock : Task {
#region Fields
private string lockName;
#endregion
#region Properties
[TaskAttribute( "resourceName",
Required = true, ExpandProperties = true )]
public string LockName {
get { return lockName; }
set { lockName = value; }
}
#endregion
#region Task overrides
/// <summary>Executes the task.</summary>
protected override void ExecuteTask() {
if ( AquireLock.mutex == null ) {
Log( Level.Error, "No lock found" );
}
else {
using ( AquireLock.mutex ) {
Log(
Level.Info,
string.Format(
"Releasing lock: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
AquireLock.mutex.ReleaseMutex();
Log(
Level.Info,
string.Format(
"Lock released: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
}
}
}
#endregion
}
Here's the build:
<?xml version="1.0" encoding="utf-8"?>
<project default="main" xmlns="http://nant.sf.net/schemas/nant.xsd"
name="Test">
<target name="main">
<loadtasks assembly="Med.NAnt.Extensions.dll" />
<aquireLock resourceName="Test" />
<sleep seconds="10"/>
<releaseLock resourceName="Test" />
</target>
</project>
I'm trying to create a pair of NAnt tasks so that I can syncronize
access to shared resources when two builds are running concurrently.
I run the two builds, the first aquires the mutex properly, sleeps ten
seconds, then releases it properly.
The second build correctly blocks when it hits WaitOne, but then throws
an AbandonedMutexException when the first build calls ReleaseMutex.
The thing is, the thread doesn't seem to be abandoned.
Here's the code.
[TaskName( "aquireLock" )]
public class AquireLock : Task {
#region Fields
[ThreadStatic]
internal static Mutex mutex;
private string lockName;
#endregion
#region Properties
[TaskAttribute( "resourceName",
Required = true, ExpandProperties = true)]
public string LockName {
get { return lockName; }
set { lockName = value; }
}
#endregion
#region Task overrides
/// <summary>Executes the task.</summary>
protected override void ExecuteTask() {
mutex = new Mutex( true, LockName );
Log(
Level.Info,
string.Format(
"Requesting lock: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
mutex.WaitOne();
Log(
Level.Info,
string.Format(
"Lock aquired: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
}
#endregion
}
[TaskName( "releaseLock" )]
public class ReleaseLock : Task {
#region Fields
private string lockName;
#endregion
#region Properties
[TaskAttribute( "resourceName",
Required = true, ExpandProperties = true )]
public string LockName {
get { return lockName; }
set { lockName = value; }
}
#endregion
#region Task overrides
/// <summary>Executes the task.</summary>
protected override void ExecuteTask() {
if ( AquireLock.mutex == null ) {
Log( Level.Error, "No lock found" );
}
else {
using ( AquireLock.mutex ) {
Log(
Level.Info,
string.Format(
"Releasing lock: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
AquireLock.mutex.ReleaseMutex();
Log(
Level.Info,
string.Format(
"Lock released: {0}, Thread {1}",
LockName,
AppDomain.GetCurrentThreadId()
)
);
}
}
}
#endregion
}
Here's the build:
<?xml version="1.0" encoding="utf-8"?>
<project default="main" xmlns="http://nant.sf.net/schemas/nant.xsd"
name="Test">
<target name="main">
<loadtasks assembly="Med.NAnt.Extensions.dll" />
<aquireLock resourceName="Test" />
<sleep seconds="10"/>
<releaseLock resourceName="Test" />
</target>
</project>