| Severity | Warning |
| Reported by | PostSharp.Patterns.Threading |
| Message | The [ExplicitlySynchronized] attribute is applied to the backing field of the automatic property <Property> but not to the property, and has no effect, because the threading model reads it from the property. Apply the attribute to the property, or set the <MSBuildProperty> MSBuild property to True to read the annotations of an automatic property and of its backing field as one. |
Cause
The ExplicitlySynchronizedAttribute attribute tells the threading model of a class that you synchronize a declaration yourself, so that the threading model neither locks nor verifies it. On an automatic property, the threading models read the attribute from the property. With the field: target, C# applies the attribute to the compiler-generated backing field instead, where the threading models do not read it.
When the threading model of a class analyzes its fields, it reports THR042 for each backing field that has the attribute while its automatic property does not. The property is then treated as if it had no attribute. <MSBuildProperty> is PostSharpUnifiedAutomaticPropertyAnnotations.
In the following example, the LastRequestId property of a synchronized class has [field: ExplicitlySynchronized].
using System;
using PostSharp.Patterns.Threading;
namespace Errors.THR042_Error;
[Synchronized]
public class RequestCounter
{
// The threading model reads [ExplicitlySynchronized] from the property, not from its backing field.
[field: ExplicitlySynchronized]
public int LastRequestId { get; set; }
public void Register( int requestId )
{
this.LastRequestId = requestId;
}
}
public static class Program
{
public static void Main()
{
var counter = new RequestCounter();
counter.Register( 42 );
Console.WriteLine( $"Last request: {counter.LastRequestId}" );
}
}
warning THR042: THR042_Error.cs(11,16): The [ExplicitlySynchronized] attribute is applied to the backing field of the automatic property Errors.THR042_Error.RequestCounter.LastRequestId but not to the property, and has no effect, because the threading model reads it from the property. Apply the attribute to the property, or set the PostSharpUnifiedAutomaticPropertyAnnotations MSBuild property to True to read the annotations of an automatic property and of its backing field as one.
Resolution
- Apply the attribute to the property itself, without the
field:target. - Alternatively, set the
PostSharpUnifiedAutomaticPropertyAnnotationsMSBuild property toTruein the project. PostSharp then reads the attributes of an automatic property and of its backing field as one set, so[field: ExplicitlySynchronized]has the effect of the attribute on the property. This setting also changes how other attributes of automatic properties are read, for example[field: Child]of the PostSharp.Patterns.Aggregation library.
<PropertyGroup>
<PostSharpUnifiedAutomaticPropertyAnnotations>True</PostSharpUnifiedAutomaticPropertyAnnotations>
</PropertyGroup>
In the following example, the attribute is applied to the property, so the threading model adds no lock to its accessors.
using System;
using PostSharp.Patterns.Threading;
namespace Errors.THR042_Fixed;
[Synchronized]
public class RequestCounter
{
// The attribute is applied to the property, where the threading model reads it.
[ExplicitlySynchronized]
public int LastRequestId { get; set; }
public void Register( int requestId )
{
this.LastRequestId = requestId;
}
}
public static class Program
{
public static void Main()
{
var counter = new RequestCounter();
counter.Register( 42 );
Console.WriteLine( $"Last request: {counter.LastRequestId}" );
}
}
Last request: 42
See Also
Reference
ExplicitlySynchronizedAttribute
SynchronizedAttribute
Other Resources
Opting In and Out From Thread Safety
Synchronized Threading Model