【问题标题】:C# TokenID: 1System.ArgumentException: An item with the same key has already been addedC# TokenID: 1System.ArgumentException: 已添加具有相同键的项
【发布时间】:2015-02-19 03:34:47
【问题描述】:

我仍在使用 C# 进行开发,突然间我遇到了这个错误。这是它记录的错误代码;

TokenID: 1System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at Butterfly.HabboHotel.Rooms.RoomManager.LoadRoom(UInt32 Id) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\HabboHotel\Rooms\RoomManager.cs:line 207
at Butterfly.Messages.GameClientMessageHandler.PrepareRoomForUser(UInt32 Id, String Password, Boolean StaffRule) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\Messages\Requests\Rooms.cs:line 528
at Butterfly.Messages.GameClientMessageHandler.OpenFlat() in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\Messages\Requests\Navigator.cs:line 177
at Butterfly.Messages.StaticMessageHandlers.SharedPacketLib.OpenFlat(GameClientMessageHandler handler) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\Messages\StaticMessageHandlers\SharedPacketLib.cs:line 372
at Butterfly.Messages.StaticMessageHandlers.StaticClientMessageHandler.HandlePacket(GameClientMessageHandler handler, ClientMessage message) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\Messages\StaticMessageHandlers\StaticClientMessageHandler.cs:line 25
at Butterfly.Messages.GameClientMessageHandler.HandleRequest(ClientMessage request) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\Messages\GameClientMessageHander.cs:line 57
at Butterfly.HabboHotel.GameClients.GameClient.parser_onNewPacket(ClientMessage Message) in c:\Users\michael-webb\Desktop\BFLY\Butterfly Emulator\HabboHotel\GameClients\GameClient.cs:line 70

这是 RoomManager.cs 第 207 行的代码 - loadedRooms.Add(Id, Room);哪个是这个虚空的一部分;

   internal Room LoadRoom(UInt32 Id)
    {
        if (IsRoomLoaded(Id))
        {
            return GetRoom(Id);
        }
        try
        {
            if (loadedRooms.ContainsValue(GetRoom(Id)))
                return GetRoom(Id);
        }
        catch { }

        RoomData Data = GenerateRoomData(Id);

        if (Data == null)
            return null;

        Room Room = new Room(Data);

        //Room Room = new Room(Data.Id, Data.Name, Data.Description, Data.Type, Data.Owner, Data.Category, Data.State,
        //    Data.UsersMax, Data.ModelName, Data.CCTs, Data.Score, Data.Tags, Data.AllowPets, Data.AllowPetsEating,
        //    Data.AllowWalkthrough, Data.Hidewall, Data.Icon, Data.Password, Data.Wallpaper, Data.Floor, Data.Landscape, Data, Data.AllowRightsOverride);

        lock (roomsToAddQueue.SyncRoot)
        {
            roomsToAddQueue.Enqueue(Room);
        }


        Room.InitBots();
        Room.InitPets();

        //Logging.WriteLine("[RoomMgr] Loaded room: \"" + Room.Name + "\" (ID: " + Id + ")");
        loadedRooms.Add(Id, Room);
        return Room;
    }

这是 Rooms.cs 第 528 行的代码 - Room room2 = ButterflyEnvironment.GetGame().GetRoomManager().LoadRoom(Id); - 这是这个虚空的一部分;

internal void PrepareRoomForUser(uint Id, string Password, bool StaffRule = false)
    {
        if (((this.Session != null) && (this.Session.GetConnection() != null)) && (this.Session.GetHabbo() != null))
        {
            this.ClearRoomLoading();
            QueuedServerMessage message = new QueuedServerMessage(this.Session.GetConnection());
            if (ButterflyEnvironment.ShutdownStarted)
            {
                this.Session.SendNotif(LanguageLocale.GetValue("shutdown.alert"));
            }
            else
            {
                if (this.Session.GetHabbo().InRoom)
                {
                    Room room = ButterflyEnvironment.GetGame().GetRoomManager().GetRoom(this.Session.GetHabbo().CurrentRoomId);
                    if (room != null)
                    {
                        room.GetRoomUserManager().RemoveUserFromRoom(this.Session, false, false);
                        this.Session.CurrentRoomUserID = -1;
                    }
                }
                Room room2 = ButterflyEnvironment.GetGame().GetRoomManager().LoadRoom(Id);
                if ((((room2 != null) && (this.Session != null)) && (this.Session.GetHabbo() != null)) && (!this.Session.GetHabbo().IsTeleporting || (this.Session.GetHabbo().TeleportingRoomID == Id)))
                {
                    this.Session.GetHabbo().LoadingRoom = Id;
                    this.CurrentLoadingRoom = room2;
                    if (this.Session.GetHabbo().SpectatorMode && (this.Session.GetHabbo().Rank < 4))
                    {
                        this.Session.GetHabbo().SpectatorMode = false;
                    }
                    if (!StaffRule)
                    {
                        IQueryAdapter adapter;
                        uint id;
                        using (adapter = ButterflyEnvironment.GetDatabaseManager().getQueryreactor())
                        {
                            adapter.setQuery("SELECT * FROM users WHERE id = '" + this.Session.GetHabbo().Id + "'");
                            foreach (DataRow row in adapter.getTable().Rows)
                            {
                                id = Convert.ToUInt32(row["lock_room"]);
                                string str = Convert.ToString(row["lock_rooms"]);
                                if (!((id <= 0) || str.Contains(Convert.ToString(room2.RoomId))))
                                {
                                    RoomData data = ButterflyEnvironment.GetGame().GetRoomManager().GenerateRoomData(id);
                                    this.Session.GetMessageHandler().PrepareRoomForUser(id, data.Password, true);
                                }
                            }
                        }

其余的不用担心。这只是其他的东西,我怎么能粘贴它。据我所知,它试图用 Id 做两次不应该做的事情?我以前从未遇到过这个错误,所以我不知道该怎么做。有人能带我去吗?

【问题讨论】:

  • 这里发生了很多事情,而且很多事情看起来很奇怪。我想知道的第一件事是 IsRoomLoaded() 是什么样的?还有,这是多线程的吗?
  • 内部布尔 IsRoomLoaded(UInt32 RoomId) { return loadedRooms.ContainsKey(RoomId); }
  • 没有理由将 .ContainsKey() 包装在另一种类似的方法中。调用 .ContainsKey() 会更清楚
  • 因为关键是要返回 Room 对象,如果它在那里,使用 TryGetValue(key, out Room)

标签: c# argumentexception


【解决方案1】:

您似乎正在将已加载的房间按 id 存储到 loadedRooms 中,并带有错误指出的语句:

loadedRooms.Add(Id, Room);

当您检查房间是否存在于此列表中时,您是按值检查。除非您覆盖 Room 对象的 equals 方法以按 id 进行比较,否则每次都使用新 Room 调用 loadedRooms 上的 ContainsValue 方法(因为您调用 GetRoom 作为参数传递)。

您的代码不共享您的loadedRooms 的数据类型,但它似乎是一个通用Dictionary,类型为Id 类型和Room。如果是这样,请不要使用ContainsValue,而是单独在 id 上尝试ContainsKey

if (loadedRooms.ContainsKey(Id))
   return GetRoom(Id);

见:https://msdn.microsoft.com/en-us/library/kw5aaea4%28v=vs.110%29.aspx

【讨论】:

  • 我自己喜欢 TryGetValue(key, out value) 范式
  • TryGetValue 将防止错误,但您永远不会根据提供的代码匹配该值。您必须通过键匹配或覆盖 Room 类的 equals 才能通过 Id 而不是引用来比较自己。
  • 我认为 OP 没有理由想要比较房间。他的第一张支票是在身份证上。我将重构此代码以仅检查 Id,使 TryGetValue 完全有效。相反,我们有一个带有错误抑制块的奇怪 Room 比较。这段代码没有意义。那么混合中也有一个队列?这里发生了很多奇怪的事情......
  • 肯定有很多陌生感。他正在比较 LoadRoom 方法的前 10 行中的房间,以查看他是否已经加载了房间以避免重新生成房间。他似乎在使用字典,并且因为他没有抓住他的字典中已经有键/值(因为没有通过字典键比较),所以他再次生成房间并收到错误将欺骗房间添加到字典中.
  • @JasonW 所以你建议修复是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-29
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2017-08-20
相关资源
最近更新 更多