| Severity | Error |
| Reported by | PostSharp.Patterns.Threading |
| Message | Method <Method> has more than one access-level attribute ([Reader], [Writer], [UpgradeableReader] or [Yielder]). Apply only one of them. |
Cause
In a class with the ReaderWriterSynchronizedAttribute aspect, each public or internal method declares the access that it needs to the object with one access-level attribute: ReaderAttribute, WriterAttribute, UpgradeableReaderAttribute or YielderAttribute. The aspect takes the matching lock when the method starts, so it must know which single lock to take.
PostSharp reports THR021 when a method has more than one of these attributes.
In the following example, the UpdatePrice method both reads and writes the price, and has both the [Reader] and [Writer] attributes.
using System;
using PostSharp.Patterns.Threading;
namespace Errors.THR021_Error;
[ReaderWriterSynchronized]
public class PriceList
{
private decimal price = 10m;
public decimal Price => this.price;
// The method reads and writes the price, but it can have only one access-level attribute.
[Reader]
[Writer]
public decimal UpdatePrice( decimal newPrice )
{
var oldPrice = this.price;
this.price = newPrice;
return oldPrice;
}
}
public static class Program
{
public static void Main()
{
var priceList = new PriceList();
var oldPrice = priceList.UpdatePrice( 12m );
Console.WriteLine( $"The price changed from {oldPrice} to {priceList.Price}." );
}
}
error THR021: THR021_Error.cs(16,20): Method Errors.THR021_Error.PriceList.UpdatePrice(System.Decimal) has more than one access-level attribute ([Reader], [Writer], [UpgradeableReader] or [Yielder]). Apply only one of them.
Resolution
Keep only the attribute that gives the method the access that it needs:
- WriterAttribute when the method modifies the object. The write lock also allows the method to read the object.
- UpgradeableReaderAttribute when the method reads the object and only sometimes modifies it, so that other readers are not blocked until it needs to write.
- ReaderAttribute when the method only reads the object.
In the following example, the UpdatePrice method has only the [Writer] attribute.
using System;
using PostSharp.Patterns.Threading;
namespace Errors.THR021_Fixed;
[ReaderWriterSynchronized]
public class PriceList
{
private decimal price = 10m;
public decimal Price => this.price;
// The write access also allows the method to read the price.
[Writer]
public decimal UpdatePrice( decimal newPrice )
{
var oldPrice = this.price;
this.price = newPrice;
return oldPrice;
}
}
public static class Program
{
public static void Main()
{
var priceList = new PriceList();
var oldPrice = priceList.UpdatePrice( 12m );
Console.WriteLine( $"The price changed from {oldPrice} to {priceList.Price}." );
}
}
The price changed from 10 to 12.
See Also
Reference
ReaderWriterSynchronizedAttribute
ReaderAttribute
WriterAttribute
UpgradeableReaderAttribute
Other Resources