久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

  • <small id='IbU16'></small><noframes id='IbU16'>

    <tfoot id='IbU16'></tfoot>

      1. <legend id='IbU16'><style id='IbU16'><dir id='IbU16'><q id='IbU16'></q></dir></style></legend>
      2. <i id='IbU16'><tr id='IbU16'><dt id='IbU16'><q id='IbU16'><span id='IbU16'><b id='IbU16'><form id='IbU16'><ins id='IbU16'></ins><ul id='IbU16'></ul><sub id='IbU16'></sub></form><legend id='IbU16'></legend><bdo id='IbU16'><pre id='IbU16'><center id='IbU16'></center></pre></bdo></b><th id='IbU16'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='IbU16'><tfoot id='IbU16'></tfoot><dl id='IbU16'><fieldset id='IbU16'></fieldset></dl></div>
          <bdo id='IbU16'></bdo><ul id='IbU16'></ul>
      3. 使用 PhysicalAddress 作為鍵時字典中的重復鍵

        Duplicate keys in Dictionary when using PhysicalAddress as the key(使用 PhysicalAddress 作為鍵時字典中的重復鍵)
          <tbody id='40gG3'></tbody>

        <i id='40gG3'><tr id='40gG3'><dt id='40gG3'><q id='40gG3'><span id='40gG3'><b id='40gG3'><form id='40gG3'><ins id='40gG3'></ins><ul id='40gG3'></ul><sub id='40gG3'></sub></form><legend id='40gG3'></legend><bdo id='40gG3'><pre id='40gG3'><center id='40gG3'></center></pre></bdo></b><th id='40gG3'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='40gG3'><tfoot id='40gG3'></tfoot><dl id='40gG3'><fieldset id='40gG3'></fieldset></dl></div>
            <tfoot id='40gG3'></tfoot>

                <legend id='40gG3'><style id='40gG3'><dir id='40gG3'><q id='40gG3'></q></dir></style></legend>
                • <bdo id='40gG3'></bdo><ul id='40gG3'></ul>

                  <small id='40gG3'></small><noframes id='40gG3'>

                  本文介紹了使用 PhysicalAddress 作為鍵時字典中的重復鍵的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

                  問題描述

                  所以我遇到了一個有趣的問題,當使用 PhysicalAddress 類型的鍵時,我在 C# 字典中得到重復鍵.這很有趣,因為它只會在很長一段時間后發生,而且我無法在完全不同的機器上使用相同的代碼在單元測試中重現它.我可以在 Windows XP SP3 機器上可靠地重現它,但只有在讓它一次運行數天之后,它才會出現一次.

                  So I have run into an interesting problem where I am getting duplicate keys in C# Dictionary when using a key of type PhysicalAddress. It is interesting because it only happens after a very long period of time, and I cannot reproduce it using the same code in a unit test on a completely different machine. I can reproduce it reliably on a Windows XP SP3 machine but only after letting it run for days at a time, and even then it only occurs once.

                  下面是我正在使用的代碼,下面是該部分代碼的日志輸出.

                  Below is the code that I am using and beneath that is the log output for that part of the code.

                  代碼:

                  private void ProcessMessages()
                  {
                      IDictionary<PhysicalAddress, TagData> displayableTags = new Dictionary<PhysicalAddress, TagData>();
                  
                      while (true)
                      {
                          try
                          {
                              var message = incomingMessages.Take(cancellationToken.Token);
                  
                              VipTagsDisappeared tagsDisappeared = message as VipTagsDisappeared;
                  
                              if (message is VipTagsDisappeared)
                              {
                                  foreach (var tag in tagDataRepository.GetFromTagReports(tagsDisappeared.Tags))
                                  {
                                      log.DebugFormat(CultureInfo.InvariantCulture, "Lost tag {0}", tag);
                  
                                      RemoveTag(tag, displayableTags);
                                  }
                  
                                  LogKeysAndValues(displayableTags);
                  
                                  PublishCurrentDisplayableTags(displayableTags);
                              }
                              else if (message is ClearAllTags)
                              {
                                  displayableTags.Clear();
                                  eventAggregator.Publish(new TagReaderError());
                              }
                              else if (message is VipTagsAppeared)
                              {
                                  foreach (TagData tag in tagDataRepository.GetFromTagReports(message.Tags))
                                  {
                                      log.DebugFormat(CultureInfo.InvariantCulture, "Detected tag ({0}) with Exciter Id ({1})", tag.MacAddress, tag.ExciterId);
                  
                                      if (tagRules.IsTagRssiWithinThreshold(tag) && tagRules.IsTagExciterValid(tag))
                                      {
                                          log.DebugFormat(CultureInfo.InvariantCulture, "Detected tag is displayable ({0})", tag);
                  
                                          bool elementAlreadyExists = displayableTags.ContainsKey(tag.MacAddress);
                  
                                          if (elementAlreadyExists)
                                          {
                                              displayableTags[tag.MacAddress].Rssi = tag.Rssi;
                                          }
                                          else
                                          {
                                              displayableTags.Add(tag.MacAddress, tag);
                                          }
                                      }
                                      else
                                      {
                                          log.DebugFormat(CultureInfo.InvariantCulture, "Detected tag is not displayable ({0})", tag);
                  
                                          RemoveTag(tag, displayableTags);
                                      }
                                  }
                  
                                  LogKeysAndValues(displayableTags);
                  
                                  PublishCurrentDisplayableTags(displayableTags);
                              }
                              else
                              {
                                  log.WarnFormat(CultureInfo.InvariantCulture, "Received message of unknown type {0}.", message.GetType());
                              }
                          }
                          catch (OperationCanceledException)
                          {
                              break;
                          }
                      }
                  }
                  
                  private void PublishCurrentDisplayableTags(IDictionary<PhysicalAddress, TagData> displayableTags)
                  {
                      eventAggregator.Publish(new CurrentDisplayableTags(displayableTags.Values.Distinct().ToList()));
                  }
                  
                  private void RemoveTag(TagData tag, IDictionary<PhysicalAddress, TagData> displayableTags)
                  {
                      displayableTags.Remove(tag.MacAddress);
                  
                      // Now try to remove any duplicates and if there are then log it out
                      bool removalWasSuccesful = displayableTags.Remove(tag.MacAddress);
                  
                      while (removalWasSuccesful)
                      {
                          log.WarnFormat(CultureInfo.InvariantCulture, "Duplicate tag removed from dictionary: {0}", tag.MacAddress);
                          removalWasSuccesful = displayableTags.Remove(tag.MacAddress);
                      }
                  }
                  
                  private void LogKeysAndValues(IDictionary<PhysicalAddress, TagData> displayableTags)
                  {
                      log.TraceFormat(CultureInfo.InvariantCulture, "Keys");
                      foreach (var physicalAddress in displayableTags.Keys)
                      {
                          log.TraceFormat(CultureInfo.InvariantCulture, "Address: {0}", physicalAddress);
                      }
                  
                      log.TraceFormat(CultureInfo.InvariantCulture, "Values");
                      foreach (TagData physicalAddress in displayableTags.Values)
                      {
                          log.TraceFormat(CultureInfo.InvariantCulture, "Address: {0} Name: {1}", physicalAddress.MacAddress, physicalAddress.Name);
                      }
                  }
                  

                  并且進程消息使用如下:

                  And process messages is used as follows:

                  Thread processingThread = new Thread(ProcessMessages);
                  

                  GetFromTagReports 代碼

                  public IEnumerable<TagData> GetFromTagReports(IEnumerable<TagReport> tagReports)
                  {
                      foreach (var tagReport in tagReports)
                      {
                          TagData tagData = GetFromMacAddress(tagReport.MacAddress);
                          tagData.Rssi = tagReport.ReceivedSignalStrength;
                          tagData.ExciterId = tagReport.ExciterId;
                          tagData.MacAddress = tagReport.MacAddress;
                          tagData.Arrived = tagReport.TimeStamp;
                  
                          yield return tagData;
                      }
                  }
                  
                  public TagData GetFromMacAddress(PhysicalAddress macAddress)
                  {
                      TagId physicalAddressToTagId = TagId.Parse(macAddress);
                  
                      var personEntity = personFinder.ByTagId(physicalAddressToTagId);
                  
                      if (personEntity.Person != null && !(personEntity.Person is UnknownPerson))
                      {
                          return new TagData(TagType.Person, personEntity.Person.Name);
                      }
                  
                      var tagEntity = tagFinder.ByTagId(physicalAddressToTagId);
                  
                      if (TagId.Invalid == tagEntity.Tag)
                      {
                          return TagData.CreateUnknownTagData(macAddress);
                      }
                  
                      var equipmentEntity = equipmentFinder.ById(tagEntity.MineSuiteId);
                  
                      if (equipmentEntity.Equipment != null && !(equipmentEntity.Equipment is UnknownEquipment))
                      {
                          return new TagData(TagType.Vehicle, equipmentEntity.Equipment.Name);
                      }
                  
                      return TagData.CreateUnknownTagData(macAddress);
                  }
                  

                  創建物理地址的位置

                  var physicalAddressBytes = new byte[6];
                  ByteWriter.WriteBytesToBuffer(physicalAddressBytes, 0, protocolDataUnit.Payload, 4, 6);
                  
                  var args = new TagReport
                  {
                      Version = protocolDataUnit.Version,
                      MacAddress = new PhysicalAddress(physicalAddressBytes),
                      BatteryStatus = protocolDataUnit.Payload[10],
                      ReceivedSignalStrength = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(protocolDataUnit.Payload, 12)),
                      ExciterId = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(protocolDataUnit.Payload, 14))
                  };
                  
                  public static void WriteBytesToBuffer(byte[] oldValues, int oldValuesStartindex, byte[] newValues, int newValuesStartindex, int max)
                  {
                      var loopmax = (max > newValues.Length || max < 0) ? newValues.Length : max;
                  
                      for (int i = 0; i < loopmax; ++i)
                      {
                          oldValues[oldValuesStartindex + i] = newValues[newValuesStartindex + i];
                      }
                  }
                  

                  注意以下幾點:

                  • messages.Tags 中的每個標簽"都包含一個新"物理地址.
                  • 返回的每個 TagData 也是新的".
                  • tagRules"方法不會以任何方式修改傳入的tag".
                  • 嘗試將 PhysicalAddress 的兩個實例(由相同字節創建)放入 Dictionary 的單獨測試會引發KeyAlreadyExists"異常.
                  • 我也嘗試了 TryGetValue,它產生了相同的結果.

                  一切正常的日志輸出:

                  2013-04-26 18:28:34,347 [8] DEBUG ClassName - Detected tag (000CCC756081) with Exciter Id (0)
                  2013-04-26 18:28:34,347 [8] DEBUG ClassName - Detected tag is displayable (Unknown: ?56081)
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Keys
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755898
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC756081
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755A27
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755B47
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Values
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755898 Name: Scotty McTester
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC756081 Name: ?56081
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755A27 Name: JDTest1
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Address: 000CCC755B47 Name: 33 1
                  2013-04-26 18:28:34,347 [8] TRACE ClassName - Current tags: Scotty McTester, ?56081, JDTest1, 33 1
                  

                  我們得到重復鍵的日志輸出:

                  Log output where we get a duplicate key:

                  2013-04-26 18:28:35,608 [8] DEBUG ClassName - Detected tag (000CCC756081) with Exciter Id (0)
                  2013-04-26 18:28:35,608 [8] DEBUG ClassName - Detected tag is displayable (Unknown: ?56081)
                  2013-04-26 18:28:35,608 [8] TRACE ClassName - Keys
                  2013-04-26 18:28:35,608 [8] TRACE ClassName - Address: 000CCC755898
                  2013-04-26 18:28:35,608 [8] TRACE ClassName - Address: 000CCC756081
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Address: 000CCC755A27
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Address: 000CCC755B47
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Address: 000CCC756081
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Values
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Address: 000CCC755898 Name: Scotty McTester
                  2013-04-26 18:28:35,618 [8] TRACE ClassName - Address: 000CCC756081 Name: ?56081
                  2013-04-26 18:28:35,648 [8] TRACE ClassName - Address: 000CCC755A27 Name: JDTest1
                  2013-04-26 18:28:35,648 [8] TRACE ClassName - Address: 000CCC755B47 Name: 33 1
                  2013-04-26 18:28:35,648 [8] TRACE ClassName - Address: 000CCC756081 Name: ?56081
                  2013-04-26 18:28:35,648 [8] TRACE ClassName - Current tags: Scotty McTester, ?56081, JDTest1, 33 1, ?56081
                  

                  請注意,所有事情都發生在單個線程上(參見 [8]),因此字典不可能同時被修改.摘錄來自相同的日志和相同的流程實例.另請注意,在第二組日志中,我們最終得到了兩個相同的鍵!

                  Notice that everything is happening on a single thread (see the [8]) so there is no chance of the dictionary having been concurrently modified. The excerpts are from the same log and the same process instance. Also notice that in the second set of logs we end up with two keys that are the same!

                  我正在調查的內容:我已將 PhysicalAddress 更改為一個字符串,以查看是否可以將其從嫌疑人列表中消除.

                  What I am looking into: I have changed PhysicalAddress to a string to see if I can eliminate that from the list of suspects.

                  我的問題是:

                  • 是否存在我在上面的代碼中沒有看到的問題?
                  • PhysicalAddress 上的相等方法有問題嗎?(那只是偶爾的錯誤?)
                  • 詞典有問題嗎?

                  推薦答案

                  Dictionary 期望不可變對象作為鍵,具有穩定的 GetHashCode/Equals 實現.這意味著對象放入字典后,GetHashCode 返回的值應該不會改變,并且對此對象所做的任何更改都不應影響 Equals 方法.

                  Dictionary expects immutable object as a key, with a stable GetHashCode / Equals implementation. This means that after object is placed into dictionary, value returned by GetHashCode should not change, and any changes made to this object should not affect Equals method.

                  雖然 PhysicalAddress 類被設計為不可變的,但它仍然包含一些擴展點,它的不變性是有缺陷的.

                  Although PhysicalAddress class was designed immutable, it still contains a few extension points, where its immutability is flawed.

                  首先,可以通過輸入字節數組來改變,不是復制而是通過引用傳遞的,像這樣:

                  First, it can be changed through input byte array, which is not copied but passed by reference, like this:

                  var data = new byte[] { 1,2,3 };
                  var mac = new PhysicalAddress(data);
                  data[0] = 0;
                  

                  第二,PhysicalAddress 不是密封類,可以通過派生來改變通過重寫 Constructor/GetHashCode/Equals 方法實現.但是這個用例看起來更像是一個 hack,所以我們將忽略它,以及通過反射進行修改.

                  Second, PhysicalAddress is not a sealed class, and can be changed by derived implementation through overriding Constructor / GetHashCode / Equals methods. But this use case looks more like a hack, so we will ignore it, as well as modifications through reflection.

                  您的情況只能通過首先將 PhysicalAddress 對象放入字典來實現,然后修改其源字節數組,然后將其包裝到新的 PhysicalAddress 實例中.

                  Your situation can only be achieved by first placing PhysicalAddress object into dictionary, and then modifying its source byte array, and then wrapping it into new PhysicalAddress instance.

                  幸運的是,PhysicalAddress 的 GetHashCode 實現只計算一次哈希,如果同一個實例被修改,它仍然被放入同一個字典桶中,并由 Equals 再次定位.

                  Luckily, PhysicalAddress' GetHashCode implementation computes hash only once, and if same instance is modified, it is still placed into same dictionary bucket, and located again by Equals.

                  但是,如果源字節數組被傳遞到 PhysicalAddress 的另一個實例,其中 hash尚未計算 - 為新的 byte[] 值重新計算哈希,找到新的存儲桶,并將副本插入字典.在極少數情況下,可以找到相同的存儲桶來自新的哈希,同樣,沒有重復插入.

                  But, if source byte array is passed into another instance of PhysicalAddress, where hash was not yet computed - hash is recomputed for new byte[] value, new bucket is located, and duplicate is inserted into dictionary. In rare cases, same bucket can be located from new hash, and again, no duplicate is inserted.

                  這是重現問題的代碼:

                  using System;
                  using System.Collections.Generic;
                  using System.Net.NetworkInformation;
                  
                  class App
                  {
                    static void Main()
                    {
                      var data = new byte[] { 1,2,3,4 };
                      var mac1 = new PhysicalAddress(data);
                      var mac2 = new PhysicalAddress(data);
                      var dictionary = new Dictionary<PhysicalAddress,string>();
                      dictionary[mac1] = "A";
                      Console.WriteLine("Has mac1:" + dictionary.ContainsKey(mac1));
                      //Console.WriteLine("Has mac2:" + dictionary.ContainsKey(mac2));
                      data[0] = 0;
                      Console.WriteLine("After modification");
                      Console.WriteLine("Has mac1:" + dictionary.ContainsKey(mac1));
                      Console.WriteLine("Has mac2:" + dictionary.ContainsKey(mac2));
                  
                      dictionary[mac2] = "B";
                      foreach (var kvp in dictionary)
                        Console.WriteLine(kvp.Key + "=" + kvp.Value);
                    }
                  }
                  

                  注意注釋行 - 如果我們取消注釋,ContainsKey"方法將預先計算 mac2 的哈希,即使修改后也是一樣的.

                  Note the commented line - if we will uncomment it, "ContainsKey" method will precompute hash for mac2, and it will be the same even after modification.

                  所以我的建議是找到生成 PhysicalAddress 實例的代碼,然后創建每個構造函數調用的新字節數組副本.

                  So my recommendation is to locate piece of code which generates PhysicalAddress instances, and create new byte array copy for each constructor call.

                  這篇關于使用 PhysicalAddress 作為鍵時字典中的重復鍵的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

                  【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

                  相關文檔推薦

                  Ignore whitespace while reading XML(讀取 XML 時忽略空格)
                  XML to LINQ with Checking Null Elements(帶有檢查空元素的 XML 到 LINQ)
                  Reading XML with unclosed tags in C#(在 C# 中讀取帶有未閉合標簽的 XML)
                  Parsing tables, cells with Html agility in C#(在 C# 中使用 Html 敏捷性解析表格、單元格)
                  delete element from xml using LINQ(使用 LINQ 從 xml 中刪除元素)
                  Parse malformed XML(解析格式錯誤的 XML)

                    1. <small id='fnLfW'></small><noframes id='fnLfW'>

                      <legend id='fnLfW'><style id='fnLfW'><dir id='fnLfW'><q id='fnLfW'></q></dir></style></legend>
                        <tfoot id='fnLfW'></tfoot>
                          <tbody id='fnLfW'></tbody>
                          <bdo id='fnLfW'></bdo><ul id='fnLfW'></ul>

                          1. <i id='fnLfW'><tr id='fnLfW'><dt id='fnLfW'><q id='fnLfW'><span id='fnLfW'><b id='fnLfW'><form id='fnLfW'><ins id='fnLfW'></ins><ul id='fnLfW'></ul><sub id='fnLfW'></sub></form><legend id='fnLfW'></legend><bdo id='fnLfW'><pre id='fnLfW'><center id='fnLfW'></center></pre></bdo></b><th id='fnLfW'></th></span></q></dt></tr></i><div class="qwawimqqmiuu" id='fnLfW'><tfoot id='fnLfW'></tfoot><dl id='fnLfW'><fieldset id='fnLfW'></fieldset></dl></div>
                          2. 主站蜘蛛池模板: 中文字幕视频在线观看 | 最新毛片网站 | 久久久久久久久久久丰满 | 中文字幕在线观看视频网站 | 91精品国产一区二区三区 | 亚洲色图第一页 | 国产九九精品视频 | 精品久 | 91精品国产一区二区三区动漫 | 亚洲精品在线视频 | 激情五月综合 | 一级片成人 | 午夜精品久久久久久久久久久久久 | 欧美久久久久久 | 亚洲天堂一区二区 | 日韩在线91 | 成年无码av片在线 | 日本a视频 | 91精品国产综合久久精品图片 | 亚洲国产黄色av | 91精品国产92 | 久久国产精品视频 | 精品久久久久久久久久久久久久 | 色综合天天天天做夜夜夜夜做 | 午夜不卡福利视频 | www.日韩| 91视频一88av| 亚洲欧美一区二区三区1000 | 国产99久久久国产精品下药 | 日韩视频高清 | 国产精品久久久久久久久久久久久久 | 亚洲成人av在线 | 久久剧场 | 99在线国产| 日韩免费福利视频 | 波多野结衣一区二区 | 日韩中文字幕一区二区三区 | 欧美区日韩区 | 精品99久久久久久 | 亚洲成av人影片在线观看 | 91久久精品一区二区二区 |