线程不会在新线程

时间:2015-05-15 17:35:24

标签: c# multithreading

我正在尝试用c#编写一个棋盘游戏,现在游戏的工作方式是游戏机制在GUI中的一个单独的类(称为GameBoard)中处理,当一个按钮在按下GUI,它会发出脉冲,应该由GameBoard检测,它可以处理动作。

我编写了一个测试,通过在一个线程中运行“takeTurn”方法来模拟这个,设置指示哪个卡被点击的静态变量,并发送脉冲,而不是等待“takeTurn”的回复表示已完成播放该卡,以便我可以执行断言以验证我想要播放的卡片已经播放。据我所知,线程正在执行,而不是作为一个线程。我在thread.Start()之后直接放置了一个print语句,并且它没有执行,代码只是挂在wait语句上(我想)。 这是测试代码:

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 个答案:

答案 0 :(得分:2)

您在GameBoard.syncObject上调用锁定,因此当您到达Monitor.Wait(GameBoard.syncObject);

时,您已经在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(隐式再次)获取锁。 (请注意"播放器:动作阶段调用播放器"直到5秒后才打印。)
  4. 主线程从睡眠中唤醒,并调用PulseAll,当Eugene指出时,它将主线程锁定在监视器等待队列上,并允许actionPhase然后获取syncObject上的锁定它是什么被封锁了。 (相关:On pulse vs enter
  5. 但现在两个线程都在调用Monitor.Wait,没有人留下来。 (或者明确地或通过退出锁{}范围释放它们的锁。)

    这有意义吗?

    Mikko是对的,我们只是在解释这个错误 - 实际上答案是使用更新的模型。任务/异步是你所追求的,并且那里有丰富的资源。查看Task.Run或其中一个任务/异步guides以帮助您入门 - 花了很多时间。