Reputation: 11344
The documentation for WeakReference<T> has the common boilerplate for thread-safety:
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
However, I'm wondering whether it is indeed safe to use instance members of WeakReference<T> anyway?
In particular, I'm wondering whether is is safe to allow concurrent access to something like this:
class MyRef<T> where T : class
{
private readonly Func<Task<T>> _fetcher;
private readonly WeakReference<T> _wref;
public MyRef(Func<Task<T>> fetcher, T target = null)
{
_fetcher = fetcher;
_wref = new WeakReference<T>(target);
}
public async Task<T> GetTargetAsync()
{
T target;
if (!_wref.TryGetTarget(out target))
{
target = await _fetcher();
_wref.SetTarget(target);
}
return target;
}
}
Both TryGetTarget
and SetTarget
are used here, possibly invoked concurrently by multiple threads.
Both of them are invoking the private external Target
property implemented by native code. (Reference source)
I'd like to know whether the native implementation really isn't safe for concurrent access before I start protecting code like the one above with synchronization locks.
What would count as safe to me here?
Simply, if I could use the code above without causing any unexpected exception or access violation due to concurrent invocations of the two methods.
More explicitly:
TryGetTarget
would either return true
and give me a non-null reference; or false
. No exceptions.
SetTarget
would not cause any exception.
Upvotes: 4
Views: 734
Reputation: 111860
By looking at the ecallist.h we can see that the internal methods of WeakTarget
/WeakTarget<T>
are implemented in the WeakReferenceNative
/WeakReferenceOfTNative
classes. Looking at their source code we can see that there is an AcquireWeakHandleSpinLock
both in the SetTarget
(used by the Target
setter) and in the GetWeakReferenceTarget
, used by the Target
getter and by the TryGetTarget
.
So probably the whole Target
/TryGetTarget
are thread safe (in the sense that they won't corrupt internal structures of .NET), but you will need a better programmer than me to check that they really are :-)
Clearly using the Target
/TryGetTarget
won't make the targetted object thread safe! That is another problem!
Upvotes: 3