In my site, I call a third party API. To avoid hitting its rate limit, I need to define a global variable to enqueue requests. (I'm using RateLimiter any better solution?)
namespace MySite.App_Start
{
public static class Global
{
public static int MaxCount { get; set; } = 30;
public static TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(1);
private static TimeLimiter rateLimiter;
public static TimeLimiter RateLimiter
{
get
{
if (rateLimiter == null)
rateLimiter = TimeLimiter.GetFromMaxCountByInterval(MaxCount, Interval);
return rateLimiter;
}
}
}
}
Then I'll use RateLimiter property. But I've read a lot that having a global variable is not a good idea. Considering my site has a lot of requests per second, is my code safe to use? Thanks.
Your code isn't 100% safe since it could create multiple instances of TimeLimiter in the beginning and depending on surrounding code, it could be a problem. I'm guessing it wouldn't be a big problem, but it's better to write the code properly to begin with.
This is something an IoC container handles nicely, but if you don't want to use one, you could use Lazy:
private static TimeLimiter rateLimiter = new Lazy(() =>
TimeLimiter.GetFromMaxCountByInterval(MaxCount, Interval));
public static TimeLimiter RateLimiter => rateLimiter.Value;
Maybe, you can make it thread-safe by using lock statement.
public static class Global
{
public static int MaxCount { get; set; } = 30;
public static TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(1);
private static object _lockObject = new object();
private static TimeLimiter rateLimiter;
public static TimeLimiter RateLimiter
{
get
{
lock (_lockObject)
{
if (rateLimiter == null)
rateLimiter = TimeLimiter.GetFromMaxCountByInterval(MaxCount, Interval);
return rateLimiter;
}
}
}
}
Your code is not thread-safety.
Try this:
public class Singleton
{
protected Singleton() { }
private sealed class SingletonCreator
{
private static readonly Singleton instance = new Singleton();
public static Singleton Instance { get { return instance; } }
}
public static Singleton Instance
{
get { return SingletonCreator.Instance; }
}
}
Or use your favorite IoC-container with creating SingleInstance object
Related
I have an application that works quite slow and I'm trying to speed it up.
I am quite new to concurrent systems, so I'm a bit stuck here.
Shortly, I can present the system as the following classes:
Some resource that is being processed
public class Resource
{
public int Capacity { get; set; } = 1000;
}
A consumer
public class Consumer
{
private readonly int _sleep;
public Consumer(int sleep)
{
_sleep = sleep;
}
public void ConsumeResource(Resource resource)
{
var capture = resource.Capacity;
Thread.Sleep(_sleep); // some calsulations and stuff
if (resource.Capacity != capture)
throw new SystemException("Something went wrong");
resource.Capacity -= 1;
}
}
And resource manager that does the job
public class ResourceManager
{
private readonly List<Consumer> _consumers;
private readonly Resource _resource;
public ResourceManager(List<Consumer> consumers)
{
_consumers = consumers;
_resource = new Resource();
}
public void Process()
{
Parallel.For(0, _consumers.Count, i =>
{
var consumer = _consumers[i];
consumer.ConsumeResource(_resource);
});
}
}
So as you saw, Consumer relies on Resource state. If you run this simulation with the following code
static void Main(string[] args)
{
var consumers = new List<Consumer>
{
new Consumer(1000),
new Consumer(900),
new Consumer(800),
new Consumer(700),
new Consumer(600),
};
var resourceManager = new ResourceManager(consumers);
resourceManager.Process();
}
you will see that when capacity of resource changes, everything breaks.
I couldn't think of any other example, and it lacks a couple of details.
First, there are many instances of Resource class, so locking access
to it would not discard all efforts to make the code concurrent.
Second, in real application this problem is very rare, so I can
sacrifice a bit of performance there.
I'm guessing this issue can be fixed with properly placed locks, but I fail to place them correctly.
As I understand the concept of locks, it prevents the locked code from being called from different threads simultaneously. Placing lock in Consumer::ConsumeResource would not help, just as placing it inside Resource::Capacity setter. I need somehow to lock modification of a resource while a consumer is doing it's job with the resource.
I hope I explained my problem efficiently. It is all quite new to me, so I'll try to make things more concrete if needed.
After thinking long and hard, I conjured a somewhat sloppy solution.
I decided to lock Resource property for a consumer using comsumer's id, and manually wait for next consumer's turn:
public class Resource
{
private int Capacity { get; set; } = 1000;
private Guid? _currentConsumer;
public int GetCapacity(Guid? id)
{
while (id.HasValue && _currentConsumer.HasValue && id != _currentConsumer)
{
Thread.Sleep(5);
}
_currentConsumer = id;
return Capacity;
}
public void SetCapacity(int cap, Guid id)
{
if (_currentConsumer.HasValue && id != _currentConsumer)
return;
Capacity = cap;
_currentConsumer = null;
}
}
public class Consumer
{
private readonly int _sleep;
private Guid _id = Guid.NewGuid();
public Consumer(int sleep)
{
_sleep = sleep;
}
public void ConsumeResource(Resource resource)
{
var capture = resource.GetCapacity(_id);
Thread.Sleep(_sleep); // some calsulations and stuff
if (resource.GetCapacity(_id) != capture)
throw new SystemException("Something went wrong");
resource.SetCapacity(resource.GetCapacity(_id) - 1, _id);
}
}
This way it works as expected, but I get a feeling that it also can be implemented with locks.
After some research about locks and stuff, I wrote that little helper class:
public class ConcurrentAccessProvider<TObject>
{
private readonly Func<TObject> _getter;
private readonly Action<TObject> _setter;
private readonly object _lock = new object();
public ConcurrentAccessProvider(Func<TObject> getter, Action<TObject> setter)
{
_getter = getter;
_setter = setter;
}
public TObject Get()
{
lock (_lock)
{
return _getter();
}
}
public void Set(TObject value)
{
lock (_lock)
{
_setter(value);
}
}
public void Access(Action accessAction)
{
lock (_lock)
{
accessAction();
}
}
}
With that, I rewrote Resource and Consumer in order to make it thread-safe:
public class Resource
{
public ConcurrentAccessProvider<int> CapacityAccessProvider { get; }
private int _capacity;
public Resource()
{
CapacityAccessProvider = new ConcurrentAccessProvider<int>(() => _capacity, val => _capacity = val);
}
public int Capacity
{
get => CapacityAccessProvider.Get();
set => CapacityAccessProvider.Set(value);
}
}
public class Consumer
{
private readonly int _sleep;
public Consumer(int sleep)
{
_sleep = sleep;
}
public void ConsumeResource(Resource resource)
{
resource.CapacityAccessProvider.Access(() =>
{
var capture = resource.Capacity;
Thread.Sleep(_sleep); // some calsulations and stuff
if (resource.Capacity != capture)
throw new SystemException("Something went wrong");
resource.Capacity -= 1;
Console.WriteLine(resource.Capacity);
});
}
}
In the provided example those manipulations effectively kill all possible profits from concurrency, but it is because there is only one Resource instance. In real world application when there are thousands of resources and only several conflicting cases, that will work just fine.
The question is a follow-up to Thread - safe singelton
I have a following class :
public class MyLazySingleton
{
// static holder for instance, need to use lambda to construct since constructor private
private static readonly Lazy<MyLazySingleton> _instance
= new Lazy<MyLazySingleton>(() => new MyLazySingleton());
// private to prevent direct instantiation.
private MyLazySingleton(string str,int i)
{
s_c1 = SingletonClass1.Instance(str);
s_c2 = SingletonClass2.Instance(str);
s_c3 = SingletonClass3.Instance(i);
}
// accessor for instance
public static MyLazySingletonInstance
{
get
{
return _instance.Value;
}
}
public void func1()
{
if (s_s1.Measure() || s_c2.Measure())
{
c_c3.Do();
}
}
static SingletonClass1 s_c1 = null;
static SingletonClass2 s_c2 = null;
static SingletonClass3 s_c3 = null;
}
I started to implement it to have a constructor with arguments, but don`t know how to proceed. Any suggestions?
I was said in comments of previous question that func1 is not thread-safe.How to make it thread-safe? Is MyLazySingleton defined to be Lazy not for thread-safety?
This page does a good job of describing how to create c# singletons, but it doesn't seem to explain how you actually use them.
http://msdn.microsoft.com/en-us/library/ff650316.aspx
So if I were to create this singleton below, how do I kick things off (I don't think I can instantiate it directly) and if I don't have an instance object how to I access it - e.g. how do I read and write to property prop1
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
public int prop1 {get; set;}
}
To use a singleton class, you simply call it's public static instance property. For example, suppose that you have a logger, and you don't want other developers to always instantiating it:
public class Logger
{
private static Logger logger = new Logger();
private Logger() { }
public static Logger Instance
{
get
{
return logger;
}
}
public void Log(text)
{
// Logging text
}
public int Mode { get; set; }
}
You should log this way:
Logger.Instance.Log("some text here");
In your case, to read/write Mode property, you should write:
Logger.Instance.Mode = 1;
int mode = Logger.Instance.Mode;
You can access the instance by using
Singleton.Instance
You only create the instance once, So you will have something like this
public sealed class Singleton
{
private static readonly Singleton instance;
private bool initialised = false;
private Singleton(){}
public static Singleton Instance
{
get
{
if(initialised)
return instance;
else {
initialsed = true;
instance = new Singleton();
return instance;
}
}
}
public int prop1 {get; set;}
}
Singleton.Instance.prop1 = 12;
I need to create a single class instance in web application that manage a queue of process. This class have multiple thread inside that look for queue and consume it.
What is the best why to do this?
I have apply singleton design pattern, but I don't understand if have to create static or normal queue inside it. Some one can give me an example please?
SOLUTION
Ok thank you! This is my singleton class:
public sealed class MyWorkingSingletonClass
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(MyWorkingSingletonClass));
private static MyWorkingSingletonClass instanza;
private static readonly object lockObject = new object();
private static ConcurrentQueue<Process> syncCoda = new ConcurrentQueue<Process>();
private MyWorkingSingletonClass()
{
}
public static MyWorkingSingletonClass Instanza
{
get
{
lock (lockObject)
{
if (instanza == null)
instanza = new PdfDucumentConverter();
return instanza;
}
}
}
public void AddProcess(Process p)
{
syncCoda.Enqueue(p);
}
public void Start()
{
Task.Factory.StartNew(WorkerTask2);
}
public static void WorkerTask2()
{
do
{
try
{
Process p;
if (syncCoda.TryDequeue(out p))
{
p.Start();
p.PriorityClass = ProcessPriorityClass.High;
p.WaitForExit();
}
}
catch (Exception ex)
{
LOG.Error(ex);
}
} while (true);
}
}
What you need is to implement new singleton class which inherits Concurrent Queue class which is thread-safe queue to ensure it will work in multi-thread environment:
public class SingletonConcurrentQueue<T> : ConcurrentQueue<T>
{
private static readonly SingletonConcurrentQueue<T>
_instance = new SingletonConcurrentQueue<T>();
static SingletonConcurrentQueue(){}
private SingletonConcurrentQueue(){}
public static SingletonConcurrentQueue<T> Instance
{
get { return _instance; }
}
}
I have a bit of code that I've been trying to examine for thread safety. I'm using the basic lazy singleton model found here. I was wondering if it is still thread safe if I'm putting the instance in the HttpApplicationState object. I need to access this instance across all instances of the web application, so if this is not thread safe how can I make it thread safe?
public sealed class EmailWorker {
private HttpApplicationState _app;
private const EMAIL_WORKER = "EmailWorker";
EmailWorker() { }
class NestedWorker {
static NestedWorker() { }
internal static readonly EmailWorker Instance = new EmailWorker();
}
public static void Initialize(HttpApplicationState appState) {
_appState = appState;
_appState.Lock();
if (_appState[EMAIL_WORKER] == null) {
_appState.Add(EMAIL_WORKER, NestedWorker.Instance);
}
_appState.UnLock();
}
public static EmailWorker Instance {
get {
// TODO: If we haven't called Initialize() first then throw exception
return (EmailWorker)_appState[EMAIL_WORKER];
}
}
}
You don't need to use Application state at all.
It should be thread-safe, but why bother?
A "standard" singleton will also be accessible across the entire application, and it won't require injecting and keeping a reference to the HttpApplicationState:
public sealed class EmailWorker
{
private EmailWorker() { }
private static class NestedWorker
{
static NestedWorker() { }
internal static readonly EmailWorker Instance = new EmailWorker();
}
public static EmailWorker Instance
{
get { return NestedWorker.Instance; }
}
}