| Severity | Warning |
| Reported by | PostSharp.Patterns.Threading |
| Message | Thread-safety policy: type <Type> must be assigned to a threading model or marked as [ExplicitlySynchronized]. |
Cause
When you add the ThreadSafetyPolicy attribute to an assembly, PostSharp checks every class of the assembly, including nested classes, and reports THR025 for each class that it does not consider thread-safe. A class is thread-safe for the policy when:
- it has no instance fields;
- it has a threading model, that is an aspect derived from ThreadAwareAttribute such as SynchronizedAttribute or ThreadAffineAttribute;
- it is marked as ExplicitlySynchronizedAttribute;
- the type analyzer of the threading library recognizes it as immutable, for example because all its fields are read-only and of immutable types.
The policy does not check structs, custom attribute classes and compiler-generated types. THR025 is a warning: the policy reminds you to choose a threading model for each class, but does not change the code.
In the following example, the ShoppingCart class has two mutable fields and no threading model.
using System;
using PostSharp.Patterns.Threading;
[assembly: ThreadSafetyPolicy]
namespace Errors.THR025_Error;
// The class has instance fields but no threading model, so the policy reports it.
public class ShoppingCart
{
private int itemCount;
private decimal total;
public void AddItem( decimal price )
{
this.itemCount++;
this.total += price;
}
public string Describe() => $"{this.itemCount} items, total {this.total}";
}
public static class Program
{
public static void Main()
{
var cart = new ShoppingCart();
cart.AddItem( 10 );
cart.AddItem( 15 );
Console.WriteLine( cart.Describe() );
}
}
warning THR025: THR025_Error.cs(9,14): Thread-safety policy: type Errors.THR025_Error.ShoppingCart must be assigned to a threading model or marked as [ExplicitlySynchronized].
Resolution
- Apply a threading model to the class, for example SynchronizedAttribute, ReaderWriterSynchronizedAttribute, ActorAttribute or ThreadAffineAttribute. The threading model then enforces the rules of thread safety.
- When the class synchronizes the access to its fields in its own code, for example with a
lockstatement, mark it as ExplicitlySynchronizedAttribute.
In the following example, the SynchronizedAttribute threading model makes ShoppingCart thread-safe.
using System;
using PostSharp.Patterns.Threading;
[assembly: ThreadSafetyPolicy]
namespace Errors.THR025_Fixed;
// The [Synchronized] threading model makes the class thread-safe, so the policy accepts it.
[Synchronized]
public class ShoppingCart
{
private int itemCount;
private decimal total;
public void AddItem( decimal price )
{
this.itemCount++;
this.total += price;
}
public string Describe() => $"{this.itemCount} items, total {this.total}";
}
public static class Program
{
public static void Main()
{
var cart = new ShoppingCart();
cart.AddItem( 10 );
cart.AddItem( 15 );
Console.WriteLine( cart.Describe() );
}
}
2 items, total 25
See Also
Reference
ThreadSafetyPolicy
ExplicitlySynchronizedAttribute
SynchronizedAttribute
Other Resources
Making a Whole Project or Solution Thread Safe
Writing Thread-Safe Code with Threading Models