Vì vậy, tôi đã gặp phải một vấn đề thú vị khi tôi nhận các khóa trùng lặp trong Từ điển C# khi sử dụng khóa kiểu PhysicalAddress. Điều này thật thú vị vì nó chỉ xảy ra sau một khoảng thời gian rất dài, và tôi không thể tái tạo nó bằng cùng một mã trong một bài kiểm tra đơn vị trên một cỗ máy hoàn toàn khác. Tôi có thể tái tạo nó một cách đáng tin cậy trên một máy Windows XP SP3 nhưng chỉ sau khi cho phép nó chạy trong nhiều ngày tại một thời điểm, và thậm chí sau đó nó chỉ xảy ra một lần.Các khóa trùng lặp trong từ điển khi sử dụng PhysicalAddress làm khóa
Dưới đây là mã mà tôi đang sử dụng và bên dưới là đầu ra nhật ký cho phần đó của mã.
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);
}
}
Và thông điệp quá trình được sử dụng như sau:
Thread processingThread = new Thread(ProcessMessages);
GetFromTagReports Mã
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);
}
đâu Physical Address được tạo ra
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];
}
}
Lưu ý những điều sau:
- Mỗi 'Tag' trong messages.Tags chứa một 'mới' PhysicalAddress.
- Mỗi Thẻ được trả về cũng là 'mới'.
- Các phương pháp 'tagRules' không sửa đổi được truyền vào 'thẻ' theo bất kỳ cách nào.
- Thử nghiệm riêng lẻ với việc cố gắng đặt hai phiên bản của PhysicalAddress (được tạo từ cùng một byte) vào một Từ điển sẽ ném ngoại lệ 'KeyAlreadyExists'.
- Tôi cũng đã thử TryGetValue và nó tạo ra kết quả tương tự.
đầu ra Log nơi mà mọi thứ vẫn ổn:
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 ra nơi mà chúng tôi có được một khóa trùng lặp:
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
Chú ý rằng tất cả mọi thứ đang xảy ra trên một sợi đơn (xem [8 ]) vì vậy không có cơ hội của từ điển đã được đồng thời sửa đổi. Các trích đoạn từ cùng một bản ghi và cùng một cá thể tiến trình. Cũng lưu ý rằng trong tập hợp nhật ký thứ hai, chúng tôi kết thúc bằng hai phím giống nhau!
Điều tôi đang xem xét: Tôi đã thay đổi PhysicalAddress thành chuỗi để xem liệu tôi có thể loại bỏ điều đó khỏi danh sách nghi phạm hay không.
Câu hỏi của tôi là:
- Có một vấn đề mà tôi không nhìn thấy trong đoạn code trên?
- Có vấn đề gì với các phương pháp bình đẳng trên PhysicalAddress không? (Đó chỉ là lỗi ngay bây giờ?)
- Có vấn đề gì với Từ điển không?
Bạn có thể nhận thấy rằng hoạt động không hoạt động không xảy ra cùng một lúc. Điều này có thể là một đối số cho thread có vấn đề. Làm thế nào bạn có thể chắc chắn rằng 'displayableTags' không phải là một đối tượng được chia sẻ? Đây có phải là biến cục bộ không? Một tài sản? Hơn nữa, sử dụng 'TryGetValue' thay vì' ContainsKey'. –
Tôi có thể chắc chắn vì 'displayableTags' là một biến được tạo cục bộ được tạo trong phương thức được gọi bởi hàm tạo Thread. Tôi đã thử TryGetValue và nó đã làm điều tương tự (tôi sẽ thêm điều đó vào câu hỏi). Ngoài ra, từ tài liệu MSDN trên TryGetValue: _Phương pháp này kết hợp chức năng của phương thức ContainsKey và thuộc tính Item._ – JohnDRoach
Bạn có thể đăng mã trong một khối không? Vấn đề có thể là bạn trong hàm Log của bạn, chúng ta có thể thấy điều đó không? –