ConcurrentDictionary找不到密钥,即使我确信它存在

本文关键字:我确信 存在 找不到 密钥 ConcurrentDictionary | 更新日期: 2023-09-27 18:20:48

在我的静态类中,我有以下内容:

static var cache = new ConcurrentDictionary<string, object>();

在线程#1中,我这样做:

cache.TryAdd (stringFromSomewhere, newlyCreatedObject); 
Console.WriteLine(stringFromSomewhere); // Outputs "abc"

线程#1后的几秒钟,在线程#2中:

if(cache.ContainsKey(stringFromSomewhereElse))
    Console.WriteLine("Yes, it exists.");
else
    Console.WriteLine("This did not exist: " + stringFromSomewhereElse);

它输出"这不存在:abc"

然后在线程#3中,在线程#2之后几秒钟:

foreach(var kvp in cache)
{
    Console.WriteLine("string: " + kvp.Key);
    if(cache.ContainsKey(kvp.Key))
        Console.WriteLine("Yes, it exists.");
    else
        Console.WriteLine("This did not exist: " + kvp.Key);
}

我得到输出"string:abc"answers"是的,它存在。"

在线程#1中,我使用MD5创建字符串,如下所示:

Convert.ToBase64String (md5.ComputeHash(Encoding.ASCII.GetBytes(value)))

在线程#2中,我从字节流中获取字符串,其中使用UTF8编码将字符串写入,然后再次使用UTF8编码器从字节中读取字符串。

在线程#3中,我通过循环ConcurrentDictionary来获得字符串。

我在这里错过了什么?据我所知,线程#2的行为应该和线程#3一样。

我有两种可能性,在我看来,这两种可能性都很渺茫:

  • 这是我没有意识到的某种同步问题吗
  • 或者字符串有什么不同?当我将它输出到控制台时,它没有什么不同

有人有其他想法或解决方案吗?

编辑:

我将数据写入流中,如下所示:

string data = System.Web.HttpUtility.UrlEncode(theString);
byte[] buffer = Encoding.UTF8.GetBytes (data);
NetworkStream stream = client.GetStream(); // TcpClient client;
stream.Write (buffer, 0, buffer.Length);

然后我从流中读取数据,如下所示:

string data = "";
NetworkStream stream = client.GetStream(); // TcpClient client;
byte[] bytes = new byte[4096];
do {   
    int i = stream.Read (bytes, 0, bytes.Length);
    data += Encoding.UTF8.GetString (bytes, 0, i);
} while(stream.DataAvailable);
string theString = HttpUtility.UrlDecode(data);

ConcurrentDictionary找不到密钥,即使我确信它存在

如果要将字节写入网络流,然后再将其读回,则必须在数据前面加一个值,说明后面有多少字节,或者需要一个数据结束标记。按照代码的编写方式,接收代码很可能只获取了部分数据。

例如,想象一下,您的密钥是"HelloWorld"。您的发送代码将字符串发送出去。接收代码在缓冲区中看到"Hello"部分,抓取它,检查是否有更多数据可用,这并不是因为网络传输线程尚未完成将其复制到缓冲区。

所以你只能得到部分字符串。

另一件可能发生的事情是你读得太多了。如果你把两个字符串写入网络流,而你的阅读器把它们都当作一个字符串来读取,就会发生这种情况。

要做正确的事情,你应该这样做:

int dataLength = buffer.Length;
byte[] lengthBuff = BitConverter.GetBytes(dataLength);
stream.Write(lengthBuff, 0, lengthBuff.Length);  // write length
stream.Write(buffer, 0, buffer.Length);  // write data

然后通过首先读取长度,然后从流中读取那么多字节来读取它。

或者,您可以使用数据结束标记:

stream.Write(buffer, 0, buffer.Length);  // write data
buffer[0] = end_of_data_byte;
stream.Write(buffer, 0, 1);  // write end of data

您的读取器读取字节,直到它得到数据标记的末尾。

您使用什么作为数据结束标记取决于您自己。它应该是正常数据流中不会出现的内容。

就我个人而言,我会选择长度前缀。

很难理解你的问题的流程,但我注意到一件事:你在网络Write()之后Flush()吗?否则,您可能会出现写入延迟,这通常会导致与时间相关的问题。