private void EnqueueRoomEventAction(BigInteger roomId, BigInteger nonce, Func<Task> action)
        {
            RoomEventActionsState roomEventActionsState = GetRoomEventActionsState(roomId);

            lock (roomEventActionsState.RoomEventActions)
            {
                roomEventActionsState.RoomEventActions.Add(Tuple.Create(nonce, action));
            }
        }
        private RoomEventActionsState GetRoomEventActionsState(BigInteger roomId)
        {
            RoomEventActionsState roomEventActionsState;
            lock (this.roomIdToRoomEventActionsMap)
            {
                if (!this.roomIdToRoomEventActionsMap.TryGetValue(roomId, out roomEventActionsState))
                {
                    roomEventActionsState = new RoomEventActionsState();
                    this.roomIdToRoomEventActionsMap.Add(roomId, roomEventActionsState);
                }
            }

            return roomEventActionsState;
        }
        public async void Update()
        {
            try
            {
                List<Func<Task>> orderedActions = new List<Func<Task>>();
                lock (this.roomIdToRoomEventActionsMap)
                {
                    foreach (KeyValuePair<BigInteger, RoomEventActionsState> roomEventActionsStatePair in this.roomIdToRoomEventActionsMap)
                    {
                        RoomEventActionsState roomEventActionsState = roomEventActionsStatePair.Value;
                        List<Tuple<BigInteger, Func<Task>>> roomEventActions = roomEventActionsState.RoomEventActions;
                        foreach (Tuple<BigInteger, Func<Task>> action in roomEventActions.Where(t => t.Item1 < 0))
                        {
                            orderedActions.Add(action.Item2);
                        }

                        roomEventActions = roomEventActions.Where(t => t.Item1 >= 0).ToList();
                        roomEventActionsState.RoomEventActions = roomEventActions;

                        lock (roomEventActions)
                        {
                            if (roomEventActions.Count == 0)
                                continue;

                            if (roomEventActionsState.NextExpectedEventNonce == null)
                            {
                                roomEventActionsState.NextExpectedEventNonce = 0;
                            }

                            BigInteger nextNonce = roomEventActionsState.NextExpectedEventNonce.Value;
                            if (roomEventActions.Find(t => t.Item1 == nextNonce) == null)
                                continue;

                            foreach (Tuple<BigInteger, Func<Task>> action in roomEventActions.OrderBy(t => t.Item1))
                            {
                                //action.Item2();
                                orderedActions.Add(action.Item2);
                                roomEventActionsState.NextExpectedEventNonce = action.Item1 + 1;
                            }

                            roomEventActions.Clear();
                        }
                    }
                }

                for (int i = 0; i < orderedActions.Count; i++)
                {
                    IEnumerable<Task> handlersTasks;
                    lock (orderedActions[i])
                    {
                        handlersTasks =
                            orderedActions[i]
                                .GetInvocationList()
                                .Cast<Func<Task>>()
                                .Select(handler => handler.Invoke());
                    }

                    await Task.WhenAll(handlersTasks);
                }
            } catch (Exception e)
            {
                Debug.LogException(e);
            }

        }