0

I have an ASP .net core API that invites guests to an event. The primary problem was that if two individuals used this same API at the same time on the same event and invited the same people, it was allowing it. After asking someone that is a JAVA developer, he informed me that they have a term called Synchronized, therefore I decided to look for the c# counterpart.

Initially, I discovered [MethodImpl(MethodImplOptions.Synchronized)] and the lock keyword, and began utilizing it to encapsulate my API. It worked fine and only allowed one person to use the API concurrently, but then I decided to add async capabilities to my API to make it quicker and not block the UI, and here is when I learned that I couldn't utilize both synchronized and lock with async.

I discovered SemaphoreSlim and its .WaitAsync(); and .Release(); keywords after doing some research. I tested it, and it worked as expected, but one thing bothered me: blocking an entire API because someone wants to add to a particular event does not seem sensible. For example, if person1 is using the API to invite people to event(A) while another person, person2 is attempting to invite people to event(B), it is illogical to block person2 from inviting to event(B), because person1 is holding the semaphore keys.

My Problem: Is there a way to use sempahoreslim or another realistic method to define a semaphoreslim key per event id rather than define a semaphore key to have just one key per API? I discovered this code after doing some research. I tested it and it worked, however my problem is that he does not remove the object from the dictionary when he is through. I want to delete it after the API has completed its work on that event. I understand how to delete stuff from dictionaries by key. But is there a better way than utilizing dictionaries to do what I'm attempting?

SpaceSloth
  • 85
  • 7
  • 1
    Related: [Asynchronous locking based on a key](https://stackoverflow.com/questions/31138179/asynchronous-locking-based-on-a-key), and also this: [How to dynamically lock strings but remove the lock objects from memory](https://stackoverflow.com/questions/33786579/how-to-dynamically-lock-strings-but-remove-the-lock-objects-from-memory). – Theodor Zoulias Oct 01 '22 at 14:29
  • 3
    There is a library https://github.com/amoerie/keyed-semaphores that implement what you want. Anyway, what if your app runs on a web farm? Those locks are not shared between processes running on different machines. If you are using a relational database to store invitations, I think it is better to relay on a unique constraint in the database `CREATE TABLE Invitations (InvitationId int, EventId int, PersonId int, CONSTRAINT uk_invitations UNIQUE(EventId, PersonId))` – Jesús López Oct 01 '22 at 16:19
  • 2
    Why are you not using a database? I assume you want to store who have been invited, so adding a suitable constraint should ensure only one invite per person-event. – JonasH Oct 01 '22 at 19:47
  • 1
    what is the problem if guests invited the same people, i think you have a kind of parallel activity, but it's not clearly defined in your question. Where is the problem if this happens and want you like to avoid – Nobody Oct 01 '22 at 22:23
  • 1
    can you add an abstract but working implementation of your current code and hints what you like to avoid ? – Nobody Oct 01 '22 at 22:28
  • 1
    @JesúsLópez there is also a very similar library https://github.com/MarkCiliaVincenti/AsyncKeyedLock which is much more performant, see benchmarks at https://github.com/MarkCiliaVincenti/AsyncKeyedLockBenchmarks. – Mark Cilia Vincenti Oct 18 '22 at 08:37

1 Answers1

1

I have made a library that solves your problem. It's an asynchronous .NET Standard 2.0 library that allows you to lock based on a key (keyed semaphores), only allowing a defined number of concurrent threads that share the same key.

For example, if you're processing transactions, you may want to limit to only one transaction per user so that the order is maintained, but meanwhile allowing parallel processing of multiple users.

https://www.nuget.org/packages/AsyncKeyedLock

Mark Cilia Vincenti
  • 1,410
  • 8
  • 25