2015-05-15 21 views
0

我想在c#中编写一个棋盘游戏,现在游戏应该工作的方式是游戏机制在单独的类(称为GameBoard)中从GUI,并且当按下GUI中的按钮时,它会发出脉冲,这应该由处理该动作的GameBoard检测到。线程不会在新线程中执行

我写了一个测试,通过在一个线程中运行“takeTurn”方法,设置指示哪个卡被点击并发送脉冲的静态变量,而不是等待来自“takeTurn “表示已完成播放该卡,以便我可以执行声明以确认我想播放的卡已播放。据我所知,线程正常执行,而不是线程。我在thread.Start()之后直接放置了一个print语句,但它没有执行,代码只是挂在一个等待语句上(我认为)。 这是测试代码:

Thread t = new Thread(new ThreadStart(p1.actionPhase)); 
t.Start(); 
Console.WriteLine("TEST: thread launched successfully"); 
GameBoard.lastCardPlayed = new Witch(); 
Console.Write("about to enter sync block."); 

lock (GameBoard.syncObject){ 
    Console.WriteLine("Entering sync block"); 
    Thread.Sleep(5000); 
    Monitor.PulseAll(GameBoard.syncObject); 
    Console.WriteLine("Button pressed!"); 
    Monitor.Wait(GameBoard.syncObject); 
    Console.WriteLine("finished waiting."); 
} 
Assert.IsTrue(p2.getDiscard().Contains(new Witch())); 

这里是代码我测试:

public override void actionPhase() 
{ 
    lock (GameBoard.syncObject) 
    { 
     Console.WriteLine("PLAYER: Action Phase called on player " + getNumber()); 
     Monitor.Wait(GameBoard.syncObject); 
     Console.WriteLine("PLAYER: Button pulse recieved."); 
     Card cardPlayed = GameBoard.lastCardPlayed; 
     playCard(cardPlayed); 
     Monitor.PulseAll(GameBoard.syncObject); 
     Console.WriteLine("PLAYER: finished playing card, pulse sent."); 
     Console.WriteLine("Playing a card with ID " + cardPlayed.getID()); 
    } 
} 

测试之前输出的唯一的事挂断的“行动阶段号召玩家1”

+1

您的方法实在太过时了,请看TAP https://msdn.microsoft.com/en-us/library/hh873175%28v=vs.110%29.aspx –

+1

'Pulse'不会保存。如果有人在你不等待的时候发生脉搏,那么它就会迷路。 – PetSerAl

+0

这就是为什么我使用Thread.Sleep,但代码甚至没有执行任何脉冲。 – icaughtfireonce

回答

2

你呼吁GameBoard.syncObject锁,所以你已经被时间上阻塞syncObject到达Monitor.Wait(GameBoard.syncObject);

你能想到的

lock(GameBoard.syncObject) 
{ 
    // Target Code 
} 

等同于:

try 
{ 
    Monitor.Enter(GameBoard.syncObject); 

    // Target Code 
} 
finally 
{ 
    Monitor.Exit(GameBoard.syncObject); 
} 

那么,为什么这是怎么回事?如果您逐步了解它,您会看到事件序列如下所示:

  1. actionPhase线程已启动。
  2. 主线程通过Monitor.Enter(隐含地通过锁)获取syncObject,然后休眠。
  3. actionPhase然后尝试通过Monitor.Enter(隐式再次)获取锁。 (请注意,“PLAYER:Action Phase on player”直到5秒后才会被打印出来。)
  4. 主线程从睡眠中醒来,并调用PulseAll,它将主线程锁定在显示器等待队列上尤金指出,它允许actionPhase然后获得它阻塞的syncObject上的锁。 (相关:On pulse vs enter

但是现在这两个线程都调用Monitor.Wait,并且没有人留下脉冲。 (或者明确地或通过退出锁定范围来释放它们的锁。)

这有道理吗?


Mikko是对的,但我们只是在解释这个错误 - 实际上答案是使用更新的模型。任务/异步是你所追求的,而且这里有丰富的资源。看看Task.Run或许多任务/异步guides之一,让你开始 - 这是花时间了。

+1

进入和退出有什么作用? – icaughtfireonce

+1

@Gene当它到达'Monitor.Wait(GameBoard.syncObject)时,'它将自身添加到特殊的监视器队列并放弃对同步对象的控制。现在它必须等待来自其他线程的'Pulse'或'PulseAll'才能重新获得锁定,但是只有在其他线程也调用'Monitor.Exit'之后。所以这个解释不幸并不能解释问题。你可以阅读更多关于脉冲[这里](http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified)或MSDN。 –

+0

@Eugene当然你是对的。这是我的粗心,会更新! – Gene