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);
如果要将字节写入网络流,然后再将其读回,则必须在数据前面加一个值,说明后面有多少字节,或者需要一个数据结束标记。按照代码的编写方式,接收代码很可能只获取了部分数据。
例如,想象一下,您的密钥是"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()吗?否则,您可能会出现写入延迟,这通常会导致与时间相关的问题。