我正在运行四个获取并设置相同属性的线程。 当我使用断点时,它会按预期给出结果,但是当我直接运行它时,它会给我最后更新的结果。
这是我的代码
int Port { get; set; }
Thread[] tMain= new Thread[4];
public void btnListen_Click(object sender, EventArgs e)
{
for (int i = 0; i < 4; i++)
{
tMain[i] = new Thread(Connect);
tMain[i].IsBackground = true;
tMain[i].Start(8000+i);
}
}
public void Connect(object _port)
{
try
{
lock ((object)Port)
{
Port = (int)_port;
}
IPEndPoint ie = new IPEndPoint(IPAddress.Any, Port);
Socket listenSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSock.Bind(ie);
listenSock.Listen(100);
Thread tListen = new Thread(() => StartListening(listenSock, Port));
tListen.IsBackground = true;
tListen.Start();
}
catch (SocketException ex)
{
MessageBox.Show(ex.Message);
}
}
public void StartListening(Socket _socket, int port)
{
Socket tempSock,listenerSocket=(Socket)_socket;
MessageBox.Show("Thread Started"+port.ToString());
while (true)
{
MessageBox.Show("Waiting For Connection");
tempSock = listenerSocket.Accept();
Thread tInner = new Thread(ProcessMessages);
tInner.IsBackground = true;
tInner.Start(tempSock);
}
}
现在我在这里看到的是代码执行时我在所有消息框中得到8003。这可能是因为前3个线程在访问时无法修改属性。在这种情况下如何获得锁定。
答案 0 :(得分:2)
这段代码肯定需要一些重构才能开始 - 太多的线程都是跨越的,并且都在非常狭窄的环境中!
简答:
问题可归结为这样一个事实:Connect
函数不是在您期望的时间(甚至是顺序)调用的,而是仅在循环结束时调用。
答案很长:
当尝试在函数中使用实例范围的变量/属性时,这是相当典型的并发问题。据我所知,没有获得Port
所需值的问题与锁本身没有直接关系。 (它可以通过这种方式解决,但不是很优雅而不是你想象的方式。)最终你无法控制如何将时间块分配给处理器级别的不同线程,因此你不知道哪些函数被执行以什么顺序。你似乎也混合了有状态和无状态(功能)设计的原则,这必然会让你陷入困境。坚持一个 - 在这种情况下最好是后者 - 你将获得更多的成功。
所以我希望我能够善待这里,说一下多线程阅读一下这可能是有益的 - 这是一个非常复杂的话题 - 并且实践了一些共同的原则。祝你好运!