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

3
我有一个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个回答

7

这里有几个问题 -

首先,回答你的问题,你需要使用volatile声明你的布尔字段:

private volatile bool doContinue = true;

说了这么多,如果有一个循环没有主体,那就非常糟糕 - 它将在该线程上使用100%的CPU,并且无限期地“旋转”。
在这种情况下,更好的方法是用等待句柄(如ManualResetEvent)替换while循环。这允许您等待重置事件并阻止直到您准备好继续执行。您可以在另一个线程中调用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
    }
}

0

你可以使用Volatile

private volatile bool docontinue = true;

0

其他人已经指出有更好的方法来解决这个问题,但我想指出你发布的代码中存在的一个问题。

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

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

docontinue 不会改变值。它一开始是 true,当消息发布时你将其设置为 true。此外,在 while 子句中你有一个 not,因此循环永远不应该运行,因为 !docontinue 总是 false。


0

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

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


0

这里有两个(可能)无限循环。而且实际上从来没有调用Wait()。

你需要在wait方法中浪费循环的原因是什么?它有什么作用?

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接