我有这个小的tcp / ip程序,对于我的生活,我无法解决这个问题(我检查了谷歌)。当我在BeginReceive的回调委托中读取缓冲区时,我将一些全局变量设置为0但是当函数启动时,变量中有数据。我在课堂上有两个全局变量:
string content;
var buffer = ((byte[]) ar.AsyncState);
int len = MySocket.EndReceive(ar);
if (len > 0)
{
string cleanMessage;
content = Encoding.ASCII.GetString(buffer, 0, len);
if (MessageLength == 0)
{
MessageLength = GetMessageLength(content);
cleanMessage = StripNumber(content);
}
else
cleanMessage = content;
if(cleanMessage.Length <1)
{
if(MySocket.Connected)
MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None,
new AsyncCallback(Read), buffer);
return;
}
if(MessageLength > cleanMessage.Length)
{
MessageLength = MessageLength - cleanMessage.Length;
amessage += cleanMessage;
}
else
{
amessage += cleanMessage.Substring(0, MessageLength);
if (OnRead != null)
{
var e = new CommandEventArgs(this, amessage);
Control target = null;
if (OnRead.Target is Control)
target = (Control)OnRead.Target;
if (target != null && target.InvokeRequired)
target.Invoke(OnRead, this, e);
else
OnRead(this, e);
}
string newMessage = cleanMessage.Substring(MessageLength);
MessageLength = GetMessageLength(newMessage);
amessage = StripNumber(newMessage);
}
MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None,
new AsyncCallback(Read), buffer);
return;
}
在我所拥有的功能的最后:
string newMessage = cleanMessage.Substring(MessageLength);
MessageLength = GetMessageLength(newMessage);
amessage = StripNumber(newMessage);
GetMessageLength(newMessage)
返回0并且StripNumber(newMessage)
返回一个空字符串,但是下次我调用该函数时,在函数开头处理任何内容之前,MessageLength = 30并且amessage包含来自之前。程序中没有其他地方可以引用这些变量,即我没有访问上述函数之外的变量,而且这两个变量都是全局变量。
答案 0 :(得分:1)
我想这里发生的事情是你有同时处理数据的并发调用,因此结果。
这有两个解决方案。第一种方法是在上面代码中触及静态(非“全局”)变量的部分周围放置锁。
第二种方法是封装对静态变量的访问(你没有完全清楚哪些变量受到影响btw),并且在封装中,同步访问(使用lock / Monitor或其他一些机制)。
然后,在上面的代码中使用局部变量,在本地复制静态变量中的值,执行工作,然后将它们分配回来。
当您必须确保上面的代码以串行方式运行时,您将使用第一个解决方案,换句话说,您必须确保读取,修改和写入都按顺序进行。
第二种方法是在你有最后一次胜利的时候。