C#共享变量在线程之间有所不同

时间:2018-12-14 20:56:09

标签: c# multithreading

在当前应用程序中,我发送UDP消息,如果服务器未确认该数据包,请在一秒钟后重新发送。现在,我正在使用易失性布尔作为终止标志,在主线程中,当收到ACK时,该标志被设置为true(由断点确认),但是此后在“ if(done)break;”期间进行。在我的另一个线程中,该标记仍然为false。

   ThreadStart processTaskThread = delegate {
            send(text);
        };
        new Thread(processTaskThread).Start();  

 void send(string text)
    {
        while (true)
        {
            byte[] data = Encoding.ASCII.GetBytes(text);
            _socket.BeginSend(data, 0, data.Length, SocketFlags.None, (ar) =>
            {
                State so = (State)ar.AsyncState;
                int bytes = _socket.EndSend(ar);
                Console.WriteLine("SEND: {0}, {1}", bytes, text);
            }, state);
            Thread.Sleep(1000);
            if (kill) break;
        }
    }

现在,如断点所确认,此处标志已正确设置为true:

  private void Receive()
    {
        _socket.BeginReceiveFrom(state.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv = (ar) =>
        {
            State so = (State)ar.AsyncState;
            int bytes = _socket.EndReceiveFrom(ar, ref epFrom);
            _socket.BeginReceiveFrom(so.buffer, 0, bufSize, SocketFlags.None, ref epFrom, recv, so);
            try { 
            string Rec = Encoding.ASCII.GetString(so.buffer, 0, bytes);

            if (Rec.StartsWith("ACK:"))
            {
                kill = true;
                return;
            }

但是回到线程循环中的条件语句,它仍然为false。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

我猜您的kill变量不是静态的,并且volatile并不意味着线程安全,因为您可以阅读here

每个线程都有自己的堆栈。如果要与多个线程共享kill变量,则需要使其为静态。当前,当您将其状态从true更改为false时,它将在第一个线程堆栈上更改,并且不会反映到第二个线程上。

您需要将其设置为静态,并确保分配是线程安全的。这可以使用Interlocked类来实现。

顺便说一句,如您所见here,在布尔值上使用互锁存在问题。解决方法是创建一个整数,对其进行递增,然后检查它是否大于零。