我正在制作一个Hangman Windows Forms应用程序,到目前为止,它一直很顺利,逻辑就在那里,但我在GUI同步方面遇到了一个小问题。
现在我正在显示来自GameForm.cs
的UI,后者又在一个单独的线程上实例化一个名为GameRound
的类,现在问题有点奇怪,游戏循环工作,问题是,它不会更新UI元素(在这种情况下是一个显示刽子手的图片框,一个显示模糊词的文本框和一个显示已经猜到的字符的标签),因为它们被调用,而是在每次迭代后更新环。但是我注意到如果我在循环中插入MessageBox.Show()
,那么它们会在调用消息框时更新。
我猜这是某种线程同步问题,其中表单不希望在Gameround线程正在工作时更新,但我是一个完整的初学者程序员所以我需要一些帮助!
以下是Gameround(Gameround.Start())
的代码 public void Start()
{
Hangman hangman = new Hangman();
do
{
//Check if hangman is dead first
if (hangman.HangmanStep == 6) {
MessageBox.Show("You got hanged! RIP");
complete = true; }
bool w_reduceSticks = new bool();
string output = WordBuilder.ObscureWord(word);
HangManBox.Image = Drawing.Drawer.DrawHangMan(hangman.HangmanStep);
WordBox.Text = output;
GuessedLetters.Text = ReturnGuessedLetters(incorrectGuesses);
MessageBox.Show("");
//After guessing check if we've guessed all letters in the word
if (CompareLists(word.dontObscure, word.letters.Distinct().ToList()))
{
System.Threading.Thread.Sleep(5000);
complete = true;
break;
}
Thread readKeyThread = new Thread(InitReadKeyForm);
readKeyThread.Start();
readKeyThread.Join();
if (ReadKeyForm.Key == 2) {
w_reduceSticks = GuessWord();
}
else {
w_reduceSticks = GuessLetters(ReadKeyForm.Key);
}
if (w_reduceSticks)
{
hangman.HangmanStep++;
}
} while (!complete);
答案 0 :(得分:0)
为什么你认为这是在一个单独的线程中运行?从各方面来看,很明显它在UI线程上运行(你将无法从UI线程外部修改UI元素)。这也是MessageBox.Show
“帮助”的原因。 Application.DoEvents
也会这样做。
在任何情况下,问题的核心是你实际上并没有在一个单独的线程中运行它。向我们展示您用来“开始新线程”的代码。
答案 1 :(得分:0)
您应该始终在创建它们的同一个线程上更新UI控件。
看看这个http://www.codeproject.com/Articles/52752/Updating-Your-Form-from-Another-Thread-without-Cre它解释了如何更新正确线程上的控件
答案 2 :(得分:0)
正如人们所说,你的ui线程没有正确更新的原因是因为在你的游戏线程中的代码执行后它没有得到优先考虑。
这可以通过添加Application.DoEvents()
(这会告诉系统几乎让其他人也能工作)或使用Lock对象来同步两个线程来解决。
作为旁注,因为我也开始阅读游戏编程,看起来正确的方法(至少到了严肃游戏的地步,我不知道那里发生了什么)来实现游戏是一回事沿着这些方向:
while (!finished){
ProcessInputs();
DoCalculations();
DrawScreen();
}
所以在这些应用程序中,它似乎都是在同一个线程中完成的。并且它有意义,因为它不像商业程序,你可以发送一个SQL查询,你不关心它向用户显示结果需要多长时间。在游戏中,您必须立即反馈用户的行为 希望我帮忙