adrianm
adrianm

Reputation: 14726

Don't use System.Threading.Timer to synchronize?

I have some code looking like this:

using System.Threading;

public sealed class MyClass : IDisposable {
    private readonly Timer _timer;

   public MyClass() {
        _timer = new Timer(MyCallback);
   }

   public void SomeMethod() {
       lock (_timer) {
           ...
       }
   }

   ...

}

When I run code analysis (FxCop) I get the error message
CA2002 : Microsoft.Reliability : 'MyClass.SomeMethod' locks on a reference of type 'Timer'. Replace this with a lock against an object with strong-identity.

I found some documentation here.

An object is said to have a weak identity when it can be directly accessed across application domain boundaries.

How can my private timer object be accessed across appdomains? The only reason I can think of is if the Timer class wraps some global system handle but I don't understand how that handle is involved in the locking.

There is a list of weak classes on the documentation page but Timer is not mentioned. MemomoryStream is also not on the list but it is included in the examples. How can a local MemoryStream object be weak?

Upvotes: 2

Views: 400

Answers (2)

Daniel A. White
Daniel A. White

Reputation: 190976

You can't be sure that Timer doesn't lock itself on its instance. Its best to use just a new object().

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502046

Timer extends MarshalByRefObject, which is why it's complaining, I suspect.

Personally I would recommend only locking on a private object which only your code can know about:

using System.Threading;

public sealed class MyClass : IDisposable {
    private readonly Timer _timer;
    private readonly object _mutex = new object();

   public MyClass() {
        _timer = new Timer(MyCallback);
   }

   public void SomeMethod() {
       lock (_mutex) {
           ...
       }
   }

   ...
}

That way you don't need to worry about whether Timer decides to lock on this etc.

Upvotes: 4

Related Questions