Open sandboxFocusImprove this doc

THR021: Method Has Several Access-Level Attributes

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

Reader/Writer Synchronized Threading Model