从C#中的另一个线程修改类属性

时间:2011-04-14 17:37:41

标签: c# multithreading sockets

我有一个C#类,它执行一个无限循环,直到条件变量设置为true。还有另一个等待网络消息的类,当接收到消息时,调用另一个类将条件变量修改为true,这样就可以退出while循环。等待消息是在一个单独的线程中完成的:

修饰符类:

public class Modifier{
Otherclass log;
private static NetworkStream theStream;
private StreamReader theInput;

public Modifier(Otherclass other, NetworkStream str)
            {
                this.log = other;
                theStream = str;
                theInput = new StreamReader(theStream);
                Thread listenThread = new Thread(new ThreadStart(listen));
                listenThread.Start();
            }

            public void listen()
            {
                while (true)
                {
                    log.postMessage(theInput.ReadLine());
                }
            }
}

另一堂课:

public class Otherclass{
    bool docontinue = true;
    public void postMessage(string input)
    {
         docontinue = true;
    }

    public void wait()
    {
          while(!docontinue)
          {
          }
    }
}

问题是虽然发送了一条消息,但程序仍然停留在while(!docontinue)。我怀疑问题是变量docontinue没有被修改但我不知道问题是否在其他地方。

5 个答案:

答案 0 :(得分:7)

这里有各种各样的问题 -

您问题的第一个直接答案是,您需要使用volatile声明布尔字段:

private volatile bool doContinue = true;

话虽如此,拥有一个没有正文的while循环的循环非常糟糕 - 它将在该线程上消耗100%的CPU,并且只是无限期地“旋转”。

更好的方法是使用WaitHandle替换while循环,例如ManualResetEvent。这允许您等待重置事件,并阻止,直到您准备好继续。在另一个线程中调用Set()以允许继续执行。

例如,试试这个:

public class Otherclass{
    ManualResetEvent mre = new ManualResetEvent(false);

    public void PostMessage(string input)
    {
         // Other stuff here...
         mre.Set(); // Allow the "wait" to continue
    }    

    public void Wait()
    {
          mre.WaitOne(); // Blocks until the set above
    }
}

答案 1 :(得分:0)

您可以使用Volatile

private volatile bool docontinue = true;

答案 2 :(得分:0)

尝试在循环中添加Thread.Sleep(100)。另请考虑使用ManualResetEvent类。

更新:即使没有Thread.Sleep,volatile等等,我刚刚检查过,wait()退出。但我的测试控制台应用程序挂起,因为listen()thead永远不会结束...

答案 3 :(得分:0)

这里有两个(可能的)无限循环。实际上没有任何东西叫Wait()

为什么你需要在wait方法中的虚拟循环中浪费周期?它有什么用途?

在我看来,postMessage应该启动一个新线程,它将执行在Wait()应该中断后需要完成的任何工作。

答案 4 :(得分:0)

其他人已经指出有更好的方法可以做到这一点,但我想在你发布的代码中指出一个问题。

public class Otherclass{
    bool docontinue = true;
    public void postMessage(string input)
    {
         docontinue = true;
    }

    public void wait()
    {
          while(!docontinue)
          {
          }
    }
}

docontinue不会更改值。它从true开始,并在发布消息时将其设置为true。最重要的是,你的while子句中没有,所以循环永远不会运行,因为!docontinue总是假的。