Mam system, który pobiera próbki. Mam wiele wątków klienta w aplikacji, które są zainteresowane tymi próbkami, ale rzeczywisty proces pobierania próbki może nastąpić tylko w jednym kontekście. Jest wystarczająco szybki, aby zablokować proces wywoływania, dopóki nie zostanie wykonane próbkowanie, ale na tyle wolny, że nie chcę, aby wiele wątków zgłaszało żądania. Wpadłem z tym wzorem (okrojona do minimalnych informacji):Czy to prawidłowy projekt synchronizacji synchronicznej?
public class Sample
{
private static Sample _lastSample;
private static int _isSampling;
public static Sample TakeSample(AutomationManager automation)
{
//Only start sampling if not already sampling in some other context
if (Interlocked.CompareExchange(ref _isSampling, 0, 1) == 0)
{
try
{
Sample sample = new Sample();
sample.PerformSampling(automation);
_lastSample = sample;
}
finally
{
//We're done sampling
_isSampling = 0;
}
}
return _lastSample;
}
private void PerformSampling(AutomationManager automation)
{
//Lots of stuff going on that shouldn't be run in more than one context at the same time
}
}
Czy to bezpieczne dla stosowania w scenariuszu opisałem?
+ 1 dla prostszego rozwiązania. –
TryEnter jest prawdopodobnie lepszy z punktu widzenia konserwacji, ponieważ najprawdopodobniej więcej ludzi będzie znało Monitor.TryEnter niż z Interlocked.CompareExchange. W tym przypadku nie martwię się zbytnio, ponieważ pobieram próbki kilka razy na sekundę. Kiedy faktycznie wykona próbkowanie, na pewno sam proces samplowania będzie nieco większy niż prymityw blokujący. –
Podoba mi się Monitor.TryEnter, ale czy nie powinniśmy używać ReaderWriterLockSlim tych dni? http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim_members.aspx –